% !Mode:: "TeX:UTF-8"
% Translator: Yujun Li 
\chapter{\glsentrytext{deep_model}中的优化}
\label{chap:optimization_for_training_deep_models}
深度学习算法在许多情况下都涉及到优化。
例如，模型中的推断（如\glssymbol{PCA}）涉及到求解优化问题。
我们经常使用解析优化去证明或设计算法。
在深度学习涉及到诸多优化问题中，最难的是\gls{NN}训练。
甚至是用几百台机器投入几天到几个月去解决一个\gls{NN}训练问题，也是很常见的。
因为这其中的优化问题很重要，代价也很高，因此开发了一组专门的优化技术。
本章会介绍神经网络训练中的这些优化技术。

如果你不熟悉基于梯度的基本优化，我们建议您查看\chapref{chap:numerical_computation}。
该章简要概述了一般的数值优化。

本章主要关注这一类优化问题：寻找神经网络上的一组参数$\Vtheta$以显著降低损失函数$J(\Vtheta)$，该损失函数通常包括整个训练集上的性能评估和正则项。

首先，我们会介绍机器学习任务训练算法中的优化和纯优化在哪些地方不一样。
接下来，我们会介绍神经网络优化很难的几个具体原因。
然后，我们会介绍几个实用算法，包括优化算法本身和初始化参数的技巧。
更高级的算法能够在训练中调整学习速率，或者使用损失函数二阶导数包含的信息。
最后，我们会介绍几个将简单优化算法融入高级过程的优化策略。

% -- 267 --

\section{学习和优化有什么不同}
\label{sec:how_learning_differs_from_pure_optimization}
用于\gls{deep_model}训练的优化算法与传统的优化算法在几个方面有所不同。
机器学习通常是间接的。
在大多数机器学习问题中，我们关注定义于测试集上的，也可能是不可解的性能度量$P$.
因此，我们只是间接地优化$P$。
我们希望通过降低损失函数$J(\Vtheta)$来提高$P$。
这一点不同于纯优化最小化$J$本身。
训练\gls{deep_model}的优化算法通常也会包括一些用于机器学习目标函数特定结构上的特殊优化。

通常，损失函数可写为训练集上的平均，如
\begin{equation}
\label{eq:8.1}
    J(\Vtheta) = \SetE_{(\RVx, \RSy) \sim\hat{p}_\text{data}} L(f(\Vx ; \Vtheta), y),
\end{equation}
其中$L$是每个样本的损失函数，$f(\Vx;\Vtheta)$是输入是$\Vx$时的预测输出，$\hat{p}_{\text{data}}$是经验分布。
监督学习中，$y$是目标输出。
在本章中，我们会介绍不带正则项的监督学习，$L$的参数是$f(\Vx;\Vtheta)$和$y$。
很容易将这种监督学习扩展成其他形式，如包括$\Vtheta$或者$\Vx$做参数，或是去掉参数$y$，以发展不同形式的正则项或是\gls{unsupervised_learning}。

\eqnref{eq:8.1}定义了训练集上的目标函数。
通常，我们更希望最小化期望取自\emph{数据生成分布}$p_{\text{data}}$而不仅是有限个训练集上的对应目标函数：
\begin{equation}
\label{eq:8.2}
    J^*(\Vtheta) = \SetE_{(\RVx, \RSy) \sim p_\text{data}} L(f(\Vx ;\Vtheta),y).
\end{equation}

\subsection{\glsentrytext{empirical_risk_minimization}}
\label{sec:empirical_risk_minimization}
机器学习算法的目标是降低\eqnref{eq:8.2}所示的期望泛化误差。
这个数据量被称为\firstgls{risk}。
值得注意的是，该期望取自真实的数据分布$p_\text{data}$。
如果我们知道了真实分布$p_\text{data}(\Vx, y)$，那么最小化风险变成了一个优化问题。
然而，我们遇到的机器学习问题，通常是不知道$p_\text{data}(\Vx, y)$，只知道训练集中的样本。

% -- 268 --

将机器学习问题转化成优化问题的最简单方法是最小化训练集上的期望损失。
这意味着用训练集上的经验分布$\hat{p}(\Vx,y)$替代真实分布$p(\Vx,y)$。
如此，我们将最小化\firstgls{empirical_risk}：
\begin{equation}
\label{eq:8.3}
    \SetE_{\RVx, \RSy \sim \hat{p}_\text{data}} [L(f(\Vx ; \Vtheta), y)]
    = \frac{1}{m} \sum_{i=1}^m L( f(\Vx^{(i)}; \Vtheta), y^{(i)}) ,
\end{equation}
其中$m$表示训练样本的数目。

基于最小化如上平均训练误差的训练过程被称为\firstgls{empirical_risk_minimization}。
在这种情况下，机器学习仍然和传统的直接优化很相似。
并非直接最优化风险，我们最优化经验风险，希望也能够很大地降低风险。
一系列不同的理论表明，在不同条件下，真实风险的期望可以下降不同的量。

然而，经验风险最小化容易过拟合。
高\gls{capacity}的模型会简单地记住训练集。
在很多情况下，经验风险最小化并非真的可行。
最有效的现代优化算法是基于梯度下降的，但是很多有用的损失函数，如$0-1$损失，没有导数（导数要么为零，要么没有定义）。
这两个问题说明，在深度学习中我们很少使用经验风险最小化。
反之，我们会使用一个稍稍不同的方法，我们真正优化的目标会更加不同于我们希望优化的目标。

\subsection{替代损失函数和\glsentrytext{early_stopping}}
\label{sec:surrogate_loss_functions_and_early_stopping}
有时，我们真正关心的损失函数（比如分类误差）并不能有效地优化。
例如，即使对于线性分类器而言，精确地最小化$0-1$损失通常是不可解的（复杂度几何级数增长于输入维数）\citep{Marcotte-92}。
在这种情况下，我们通常会优化\firstgls{surrogate_loss_function}。
替代损失函数作为原目标的代理，还有一些优点。  
例如，正确类别的负对数似然通常用作$0-1$损失的替代。
负对数似然允许模型估计给定样本的条件概率，如果该模型效果好，那么它能够输出最小期望分类误差对应的类别。

% -- 269 --

在某些情况下，替代损失函数能比原函数学习到更多。
例如，使用对数似然替代函数时，在训练集上的$0-1$损失达到$0$之后，测试集上的$0-1$损失还能持续下降很长一段时间。
这是因为即使$0-1$损失期望是零时，我们还能拉开不同类别的距离以改进分类器的鲁棒性，获得一个更强壮的，值得信赖的分类器。
因而，相较于简单地最小化训练集上的平均$0-1$损失，从训练数据中抽取了更多信息。

一般的优化和我们用于训练算法的优化的一个重要不同之处在于，训练算法通常不会停在一个局部最小处。
反之，机器学习通常会优化一个替代损失函数，并停止在基于\gls{early_stopping}（\secref{sec:early_stopping}）的收敛条件满足的情况。
通常，\gls{early_stopping}是基于真实损失函数，如验证集上的$0-1$损失，并被设计用于将算法终止于过拟合发生之前。
训练过程通常终止于替代损失函数仍有较大的导数时，这和纯优化非常不同。
纯优化通常会考虑算法收敛到梯度很小的时候。

\subsection{批算法和\gls{minibatch}算法}
\label{sec:batch_and_minibatch_algorithms}
机器学习算法和一般优化算法不同的一点是，机器学习算法的目标函数通常可以分解为训练样本上的求和。
机器学习优化算法通常使用整个损失函数中的一部分项去更新其参数。

例如，最大似然估计问题可以在对数空间中分解成每个样本的总和：
\begin{equation}
\label{eq:8.4}
    \Vtheta_{\text{ML}} = \underset{\Vtheta}{\argmax} \sum_{i=1}^m
    \log p_{\text{model}} (\Vx^{(i)}, y^{(i)}; \Vtheta) .
\end{equation}

最大化这个总和等价于最大化训练集在经验分布上的期望：
\begin{equation}
\label{eq:8.5}
    J(\Vtheta) = \SetE_{\RVx, \RSy \sim\hat{p}_\text{data}} 
    \log p_{\text{model}} (\Vx,y ; \Vtheta) .
\end{equation}

% -- 270 --

优化算法用到的目标函数$J$中的大多数性质也是训练集上的期望。
例如，最常用的性质是导数：
\begin{equation}
\label{eq:8.6}
    \nabla_{\Vtheta} J(\Vtheta) = \SetE_{\RVx, \RSy \sim\hat{p}_{\text{data}}} 
    \nabla_{\Vtheta} \log p_{\text{model}} (\Vx,y; \Vtheta) .
\end{equation}

准确计算这个期望的计算量非常大，因为需要计算整个数据集上的每个样本。
在实践中，我们可以从数据集中随机采样少量的样本，然后计算这些样本上的平均值。

回想一下，$n$个样本的均值标准误差（\eqnref{eq:5.46}）是$\sigma/\sqrt{n}$，其中$\sigma$是样本值真实的\gls{standard_deviation}。
分母$\sqrt{n}$表明使用更多样本来估计梯度的方法的回报是低于线性的。
比较两个假想的梯度计算，一个基于$100$个样本，另一个基于$10,000$个样本。
后者的计算量多于前者的$100$倍，但却只降低了$10$倍的标准差。
如果能够快速计算出梯度估计值，而不是缓慢计算准确值，那么大多数优化算法会收敛地更快（就总的计算量而言，而不是指更新次数）。

另一个从小数目样本中估计梯度的动机是训练集的冗余。
在最坏的情况下，训练集合中所有的$m$个样本可以是彼此相同的拷贝。
基于采样的梯度估计可以使用单个样本计算出正确的梯度，而比原来的做法少花了$m$倍时间。
实践中，我们不太可能真的遇到这种最坏情况，但我们可能会发现大量样本都对梯度做出了非常相似的贡献。

使用整个训练集的优化算法被称为\firstgls{batch}或\firstgls{deterministic}梯度算法，因为它们会同时大\gls{batch}地处理所有的样本。
这个术语可能有点令人困惑，因为这个词``\gls{batch}''也经常被用来描述\gls{minibatch}随机梯度下降算法中用到的\gls{minibatch}样本。
通常，术语``\gls{batch}梯度下降''指使用全部训练集，而术语"\gls{batch}"单独出现时指一组样本。
例如，我们普遍使用术语``\gls{batch}大小''表示\gls{minibatch}的大小。

每次只使用单个样本的优化算法有时被称为\firstgls{stochastic}或者\firstgls{online}算法。
术语``\gls{online}''通常是指从连续产生样本的数据流中抽取样本的情况，而不是从一个固定大小的训练集中遍历多次采样的情况。

% -- 271 --

大多数用于深学习的算法介于以上两者之间，使用一个以上，而又不是全部的训练样本。
传统上，这些会被称为\firstgls{minibatch}或\firstgls{minibatch_stochastic}方法 ，现在通常将他们简单地称为\firstgls{stochastic}方法。

随机方法的典型示例是\gls{SGD}，参看\secref{sec:stochastic_gradient_descent_chap8}中的细节。

\gls{minibatch}大小通常由以下原因驱动：
\begin{itemize}
    \item 更大的\gls{batch}会计算更精确的梯度估计，但是回报却是小于线性的。
    
    \item 多核架构通常未充分利用极小\gls{batch}。
    这促使我们使用一些绝对最小\gls{batch}，低于这个值的小\gls{batch}处理不会减少计算时间。
    
    \item 如果\gls{batch}处理中的所有样本可以并行地预处理（通常确是如此），那么内存消耗和\gls{batch}大小会成比增长。
    对于很多硬件设施，这是\gls{batch}大小的限制因素。
    
    \item 有些硬件在特定大小的数列上效果更好。
    尤其是在使用GPU时，通常使用$2$的幂数作为\gls{batch}大小来获得更少的运行时间。
    一般，$2$的幂数的取值范围是$32$到$256$，$16$有时用于尝试大的模型。
    
    \item 
    可能是由于小\gls{batch}处理在学习过程中加入了\gls{noise}，它们会有一些正则化效果\citep{Wilson-2003}。
    泛化误差通常在\gls{batch}大小为$1$时最好。
    因为梯度估计的高方差，小\gls{batch}训练需要较小的学习速率以维持稳定性。
    由于降低的学习速率和消耗更多步骤来观察整个训练集而产生更多的步骤，会导致总的运行时间非常大。
\end{itemize}

不同的算法使用不同的方法从\gls{minibatch}中获取不同的信息。
有些算法对采样误差比其他算法更敏感，有两个可能原因。
一个是它们使用了很难在少量样本上精确估计的信息，另一个是它们以放大采样误差的方式使用了信息。
仅基于梯度$\Vg$的更新方法通常相对鲁棒，并能处理更小的\gls{batch}，如$100$。
使用\gls{hessian}矩阵$\MH$，计算如$\MH^{-1}\Vg$的梯度的二阶方法通常需要更大的\gls{batch}，如$10,000$。
这些大\gls{batch}需要最小化估计$\MH^{-1}\Vg$的波动。
假设$\MH$被精确估计，但是有一个很差的条件数。
乘以$\MH$或是其逆会放大之前存在的误差（这个示例中是指$\Vg$的估计误差）。
即使$\MH$被精确估计，$\Vg$中非常小的变化也会导致更新$\MH^{-1}\Vg$中非常大的变化。
当然，我们通常只会近似地估计$\MH$，因此相较于我们使用具有较差条件的操作去估计$\Vg$，更新$\MH^{-1}\Vg$会含有更多的误差。

% -- 272 --

\gls{minibatch}是随机抽取的这点也很重要。
从一组样本中计算出梯度期望的无偏估计需要这些样本是独立的。
我们也希望两个连续的梯度估计是互相独立的，因此两个连续的\gls{minibatch}样本也应该是彼此独立的。
很多现实的数据集中，连续的样本之间具有高度相关性。
例如，假设我们得到了一个长长的血液样本测试结果清单。
清单上的数据有可能是这样获取的，头五个血液样本于不同时间段取自第一个病人，接下来三个血液样本取自第二个病人，再随后的血液样本取自第三个病人，等等。
如果我们从这个清单上顺序抽取样本，那么我们的每个\gls{minibatch}数据都极为有偏，因为这个\gls{minibatch}很可能只代表着数据集上众多患者中的某一个患者。
在这种数据集中的顺序有很大影响的情况下，很有必要在抽取\gls{minibatch}样本前打乱样本顺序。
对于非常大的数据集，如数据中心含有几十亿样本的数据集，我们每次构建\gls{minibatch}样本时都将样本完全均匀地抽取出来是不太现实的。
幸运的是，实践中通常将样本顺序打乱一次之后存储起来就足够了。
这将会固定以后训练模型时会用到的一组组\gls{minibatch}连续样本，每个独立的模型每次遍历训练数据时都会重复使用这个顺序。
然而，这种偏离真实随机采样的方法并非具有很严重的有害影响。
不曾打乱样本顺序的方法才会极大地降低算法的性能。

很多机器学习上的优化问题都可以分解成并行地计算不同样本上单独的更新。
换言之，我们在计算\gls{minibatch}样本$\MX$上的最小化$J(\MX)$的更新时，同时可以计算其他\gls{minibatch}样本上的更新。
这类异步并行分布式方法将在\secref{sec:large_scale_distributed_implementations}中进一步讨论。

\gls{minibatch}随机梯度下降的一个有趣动机是，只要没有重复使用样本，
它将遵循着真实\emph{\gls{generalization_error}}（\eqnref{eq:8.2}）的梯度。
很多\gls{minibatch}随机梯度下降方法的实现会打乱数据顺序一次，然后多次遍历数据更新参数。
第一次遍历时，每个\gls{minibatch}样本都用来计算真实泛化误差的无偏估计。
第二次遍历时，估计将会是有偏的，因为它重新抽取了已经用过的样本，而不是从和原先样本相同的数据生成分布中获取新的样本。

% -- 273 --

随机梯度下降最小化泛化误差的原因很容易从在线学习的情况中看出来，
这时样本或者\gls{minibatch}都是从数据\firstgls{stream}中抽取出来的。
换言之，并非获取固定大小的训练集，学习器好像是一个每次看到新样本的人，
每个样本$(\Vx,y)$都来自数据生成分布$p_{\text{data}}(\Vx,y)$。
这种情况下，样本从来不会重复；每次更新也是公平地从分布$p_\text{data}$中采样获得。

在$\Vx$和$y$是离散时，以上的等价性很容易得到。
在这种情况下，\gls{generalization_error}（\eqnref{eq:8.2}可以表示为
\begin{equation}
\label{eq:8.7}
    J^*(\Vtheta) = \sum_{\Vx} \sum_y p_{\text{data}}(\Vx, y) L(f(\Vx; \Vtheta),y),
\end{equation}
上式的准确梯度为
\begin{equation}
\label{eq:8.8}
    \Vg = \nabla_{\Vtheta} J^*(\Vtheta) = \sum_{\Vx} \sum_y p_{\text{data}}
    (\Vx, y) \nabla_{\Vtheta} L(f(\Vx;\Vtheta),y) .
\end{equation}
在\eqnref{eq:8.5}和\eqnref{eq:8.6}中，我们已经在对数似然中看到了相同的结果；现在我们发现这一点在包括似然的其他函数$f$上也是成立的。
在$p_\text{data}$和$L$上有一些温和的假设时，类似的结果在$\Vx$和$y$是连续时也能得到。

因此，泛化误差的准确梯度的无偏估计可以通过从数据生成分布$p_\text{data}$抽取\gls{minibatch}样本$\{ \Vx^{(1)}, \dots,\Vx^{(m)} \}$以及对应的标签$y^{(i)}$，然后计算该\gls{minibatch}上损失函数对应参数的梯度
\begin{equation}
\label{eq:8.9}
    \hat{\Vg} = \frac{1}{m} \nabla_{\Vtheta} \sum_i L(f(\Vx^{(i)};\Vtheta),y^{(i)} ).
\end{equation}
在泛化误差上执行SGD方法使用方向$\hat{\Vg}$更新$\Vtheta$。

当然，这个解释只能用于样本没有重复使用的情况。
然而，除非训练集特别大，通常最好是多次遍历训练集。
当多次遍历数据集更新时，只有第一遍满足泛化误差的梯度无偏估计。
但是，额外的遍历更新会由于减小训练误差而得到足够的好处，以抵消其带来的训练误差和测试误差间差距的增加。

% -- 274 --

随着数据集的规模迅速增长，超越了计算能力的增速，
机器学习应用越来越普遍每个样本只使用一次，甚至是不完整地使用训练集。
在使用一个非常大的训练集时，过拟合不再是问题，而欠拟合和计算效率变成了主要的顾虑。
也可以参看\cite{bottou-bousquet-2008}中关于训练样本数目增长时，泛化误差上计算瓶颈影响的讨论。

\section{神经网络的优化挑战}
\label{sec:challenges_in_neural_network_optimization}
优化通常是一个极其困难的任务。
通常，机器学习会小心设计目标函数和约束，以确保优化问题是凸的，
从而避免一般优化问题的复杂度。
在训练神经网络时，我们肯定会遇到一般的非凸情况。
即使是凸优化，也并非没有任何问题。
在这一节中，我们会总结几个训练\gls{deep_model}时会涉及到的主要挑战。

\subsection{病态}
\label{sec:ill_conditioning}
在优化凸函数时，会遇到一些挑战。
这其中最突出的是\gls{hessian}矩阵$\MH$的病态（ill-conditioning）。
这是数值优化，凸优化或其他形式的优化中普遍存在的问题，更多细节请参看\secref{sec:beyond_the_gradient_jacobian_and_hessian_matrices}。

病态问题一般被认为存在于神经网络训练过程中。
病态体现在随机梯度下降会``卡''在某些情况，此时即使很小的更新步长也会增加损失函数。

回顾\eqnref{eq:4.9}，损失函数的二阶系列展开预测梯度下降中的$-\epsilon\Vg$会增加
\begin{equation}
    \frac{1}{2} \epsilon^2 \Vg^\top \MH\Vg - \epsilon\Vg^\top\Vg
\end{equation}
到损失中。
当$\frac{1}{2} \epsilon^2 \Vg^\top\MH\Vg$超过$\epsilon\Vg^\top\Vg$时，梯度的病态会成为问题。
判断病态是否不利于神经网络训练任务，我们可以检测梯度平方范数$\Vg^\top\Vg$和$\Vg^\top \MH\Vg$。
在很多情况中，梯度范数不会在训练过程中显著缩小，但是$\Vg^\top\MH\Vg$的增长会超过一个数量级。
其结果是尽管梯度很强，学习会变得非常缓慢，因为学习率必须收缩以弥补更强的曲率。
如\figref{fig:chap8_grad_norm_increases}所示，成功训练的神经网络中，梯度显著增加。

\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter8/figures/grad_norm_increases_color}}
\fi
\caption{\gls{GD}通常不会到达任何类型的\gls{critical_points}。
此示例中，在用于对象检测的卷积网络的整个训练期间， 梯度范数持续增加。
(左)各个梯度计算的范数如何随时间分布的散点图。
为了提高可读性，每\gls{epoch}仅绘制一个梯度范数。 
我们将所有梯度范数的移动平均绘制为实曲线。
梯度范数明显随时间增加，而不是如我们所期望的那样随训练过程收敛到\gls{critical_points}而减小。
(右)尽管梯度递增，训练过程却相当成功。 
验证集上的分类误差可以降低到较低水平。
}
\label{fig:chap8_grad_norm_increases}
\end{figure}


% -- 275 --

尽管病态存在于包括神经网络训练的其他情况中，有些适用于其他情况的解决病态的技术并不适用于神经网络。
例如，牛顿法在解决糟糕条件的\gls{hessian}矩阵时，是一个非常优秀的工具，
但是我们将会在以下小节中说明牛顿法运用在神经网络前需要很大的改动。

\subsection{局部极小值}
\label{sec:local_minima}
凸优化问题的一个突出特点是其可以归约为寻找一个局部极小值的问题。
任何一个局部极小值都是全局最小值。
有些凸函数的底部是一个平坦的区域，而不是单一的全局最小点，但该平坦区域中的任意点都是可行最优解。
优化一个凸问题时，若发现了任何形式的临界点，我们都会知道已经找到了一个很好的解。

% -- 276 --

对于非凸函数时，如神经网络，有可能会存在多个局部极小值。
事实上，几乎所有的\gls{deep_model}基本上都会有非常多的局部极小值。
然而，我们会发现这并不是一个严重的问题。

由于\firstgls{model_identifiability}问题，神经网络和任意具有多个等效参数化\gls{latent_variable}的模型都会具有多个局部极小值。
如果一个足够大的训练集可以唯一确定一组模型参数，那么该模型被称为可辨认的。
带有\gls{latent_variable}的模型通常是不可辨认的，因为通过批次交换\gls{latent_variable}我们能得到等价的模型。
例如，考虑神经网络的第一层，我们可以交换单元$i$和单元$j$的传入权重向量，传出权重向量而得到等价的模型。
如果神经网络有$m$层，每层有$n$个单元，那么会有$n!^m$方式重新排布\gls{hidden_unit}。
这种不可辨认性被称为\firstgls{weight_space_symmetry}。

包括权重空间对称性，很多神经网络还有其他导致不可辨认的原因。
例如，在任意\gls{rectified_linear}网络或者\gls{maxout}网络中，
我们可以放大传入权重和\gls{bias_aff}$\alpha$倍，然后缩小传出权重$\frac{1}{\alpha}$倍，而保持模型等价。
这意味着，如果损失函数不包括如权重衰减这种直接依赖于权重而非模型输出的项，那么\gls{rectified_linear}网络或者\gls{maxout}网络的每一个局部极小解都在等价局部极小解的$(m\times n)$维双曲线上。

这些\gls{model_identifiability}问题意味着神经网络损失函数具有非常多，甚至无限多的局部极小解。
然而，所有这些由于不可辨识性问题产生的局部极小解都有相同的损失函数值。
因此，这些局部极小解并非是非凸所带来的问题。

如果局部极小解和全局极小解相差很大时，那么此时多个局部极小解会带来很大的隐患。
我们可以构建没有\gls{hidden_unit}的小规模神经网络，其局部极小值和全局极小值相差很远\citep{Sontag-cs89,Brady89,Gori-pami91}。
如果偏差严重的局部极小值是常见的，那么这将给基于梯度的优化算法带来极大的问题。

% -- 277 --

对于实际中感兴趣的网络，是否存在大量偏差严重的局部极小值，优化算法是否会碰到这些局部极小值，都是尚未解决的公开问题。
多年来，大多数从业者认为局部极小值是困扰神经网络优化的常见问题。
如今，情况有所变化。
这个问题仍然是学术界的热点问题，但是学者们现在猜想，对于足够大的神经网络而言，
大部分局部极小值都具有很小的损失函数，我们能不能找到真正的全局极小值并不重要，而是需要在参数空间中找到一个具有很少损失的点\citep{Saxe-et-al-ICLR13,Dauphin-et-al-NIPS2014-small,GoodfellowOptimization15,Choromanska-et-al-AISTATS2015}。

很多从业者将神经网络优化中的所有困难都归结于局部极小值。
我们鼓励从业者要仔细测试特定的问题。
一种能够排除局部极小值是主要问题的检测方法是画出梯度范数随时间的变化。
如果梯度范数没有缩小到一个微小的值，那么该问题既不是局部极小值，也不是其他形式的临界点。
这种消极的测试可以排除局部极小值是造成问题的原因。
在高维空间中，很难正面证明并非是局部极小值导致的问题。
许多并非局部极小值的结构也具有很小的梯度。

\subsection{高原，\glsentrytext{saddle_points}和其他平坦区域}
\label{sec:plateaus_saddle_points_and_other_flat_regions}
对于很多高维非凸函数而言，局部极小值（或极大值）事实上都远少于另一类梯度为零的点：\gls{saddle_points}。
\gls{saddle_points}附近的某些点比\gls{saddle_points}有更大的损失，而其他点则有更小的损失。
在\gls{saddle_points}处，\gls{hessian}矩阵同时具有正负特征值。
位于正特征值对应的特征向量方向的点比\gls{saddle_points}有更大的损失，反之，位于负特征值对应的特征向量方向的点有更小的损失。
我们可以将\gls{saddle_points}视为损失函数某个横截面上的局部极小值，同时也可以视为损失函数某个横截面上的局部极大值。
如\figref{fig:chap4_saddle_3d_color}所示。

多类随机函数表现出以下性质：低维空间中，局部极小值很普遍。
在更高维空间中，局部极小值很少，而\gls{saddle_points}则很常见。
对于这类函数$f:\SetR^n \to \SetR$而言，\gls{saddle_points}和局部极小值的数目比率期望随$n$指数级增长。
直觉上理解这种现象，我们可以观察到海森矩阵在局部极小点处只有正特征值。
而在\gls{saddle_points}处，\gls{hessian}矩阵则同时具有正负特征值。
试想一下，每个特征值的正负号由抛硬币决定。
在一维情况下，很容易抛硬币得到正面朝上一次而获取局部极小值。
在$n$-维空间中，指数级不太可能$n$次抛掷硬币都得到正面朝上。
参看\cite{Dauphin-et-al-NIPS2014-small}，回顾相关理论工作。

% -- 278 --

很多随机函数一个惊人性质是，当我们到达损失较低的区间时，\gls{hessian}矩阵的特征值为正的可能性更大。
和抛硬币类比，这意味着如果我们处于低损失的临界点时，抛掷硬币正面朝上$n$次的概率更大。
换言之，局部极小值具有低损失的可能性比高损失要大得多。
具有高损失的临界点更有可能是\gls{saddle_points}。
具有极高损失的临界点就很可能是局部极大点了。

以上现象出现在许多类随机函数中。
那么是否在神经网络中也有发生呢？
\cite{Baldi89}从理论上证明，不具非线性的浅层\gls{AE}（\chapref{chap:autoencoders}中将介绍的训练输入到输出的前馈网络）只有全局极小值和\gls{saddle_points}，没有损失比全局极小值更大的局部极小值。
他们还发现这些结果能够扩展到不具非线性的更深层网络上，不过没有证明。
这类网络的输出是其输入的线性函数，但它们仍然有助于分析非线性神经网络模型，因为它们的损失函数是关于参数的非凸函数。
这类网络本质上是多个矩阵组合在一起。
\cite{Saxe-et-al-ICLR13}精确解析了这类网络中的完整学习动态，表明这些模型的学习能够捕捉，训练具有非线性激励函数的\gls{deep_model}中的许多定性特征。
\cite{Dauphin-et-al-NIPS2014-small}实验表明，真实的网络也会有包含很多高损失\gls{saddle_points}的损失函数。
\cite{Choromanska-et-al-AISTATS2015}理论证明了另一类和神经网络相关的高维随机函数也满足这种情况。

训练算法时的\gls{saddle_points}扩散会有哪些影响呢？
对于只使用梯度信息的一阶优化算法而言，情况是不明的。
\gls{saddle_points}附近的梯度通常会非常小。
另一方面，实验中梯度下降似乎可以在许多情况下逃离\gls{saddle_points}。
\cite{GoodfellowOptimization15}可视化了最新神经网络的几个学习轨迹，如\figref{fig:chap8_plot_atmu_relu_5}所示。
这些可视化显示权重都为零的\gls{saddle_points}附近，损失函数都是平坦的。
但是他们也展示了梯度下降轨迹能够迅速逸出该区间。
\cite{GoodfellowOptimization15}还认为，或许可以解析地表明连续时间的梯度下降会逃离，而不是吸引，附近的\gls{saddle_points}，但是对于梯度下降更现实的使用，情况或许是不同的。

\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter8/figures/plot_atmu_relu_5}}
\fi
\caption{神经网络\gls{cost_function}的可视化。
这些可视化对应用于真实对象识别和自然语言处理任务的前馈神经网络、卷积网络和\gls{recurrent_network}而言是类似的。
令人惊讶的是，这些可视化通常不会显示出很多明显的障碍。
大约2012年，在\gls{SGD}开始成功训练非常大的模型之前，神经网络\gls{cost_function}的表面通常被认为有更多的非凸结构（相比这些投影所显示的）。
该投影所显示的主要障碍是初始参数附近的高代价\gls{saddle_points}，但如由蓝色路径所示，\glssymbol{SGD}训练轨迹能轻易地逃脱该鞍点。
大多数训练时间花费在横穿\gls{cost_function}的相对平坦峡谷，可能由于梯度中的高噪声、或该区域中\gls{hessian}矩阵的不良条件数，或者简单地需要经过间接的弧路径环绕图中可见的高``山'' 。
图经\citet{GoodfellowOptimization15}许可改编。
}
\label{fig:chap8_plot_atmu_relu_5}
\end{figure}

对于牛顿法而言，显然\gls{saddle_points}会是一个问题。
梯度下降旨在朝``下坡路''移动，而非明确寻求临界点。
而牛顿法的目标是寻求梯度为零的点。
没有适当的修改，牛顿法会跳进一个\gls{saddle_points}。
高维空间中\gls{saddle_points}的扩散或许解释了为什么二阶方法不能成功替换梯度下降用于神经网络训练中。
\cite{Dauphin-et-al-NIPS2014-small}介绍了二阶优化的\firstgls{saddle_free_newton_method}，并表明和传统算法相比有显著改进。
二阶方法仍然难以扩展到大型神经网络，但是如果这类无鞍算法能够扩展的话，还是很有希望的。

% -- 279 --

除了极小点和\gls{saddle_points}，还存在其他梯度为零的点。
例如从优化的角度看与\gls{saddle_points}很相似的极大点，很多算法不会收敛到极大点，然而未修改的牛顿法会。
和极小点一样，许多类的随机函数的极大点在高维空间中也是指数级稀少。

也可能会有恒值的宽而平坦的区域。
在这些区间，梯度和\gls{hessian}矩阵都是零。
这种退化的情形是所有数值优化算法的主要问题。
在凸问题中，一个宽而平的区间肯定包含全局极小值，但是对于一般的优化问题而言，
这样的区域可能会对应着目标方程中一个较高的值。

% -- 280 --

\subsection{悬崖和梯度爆炸}
\label{sec:cliffs_and_exploding_gradients}
多层神经网络通常有像悬崖一样的斜率较大区域，如\figref{fig:chap8_cliff}所示。
这是由于几个较大的权重相乘导致的。
遇到斜率极大的悬崖结构时，梯度更新会很大程度地改变参数值，通常会跳过这类悬崖结构。

\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter8/figures/cliff_color}}
\fi
\caption{高度非线性的\gls{DNN}或\gls{RNN}的\gls{objective_function}通常包含由几个参数连乘导致的参数空间中尖锐非线性。
这些非线性在某些区域会产生非常大的导数。
当参数接近这样的悬崖区域时，梯度下降更新可以使参数弹射得非常远，可能会无效化已经完成的大量优化工作。
图经 \citet{Pascanu+al-ICML2013-small}许可改编。}
\label{fig:chap8_cliff}
\end{figure}


不管我们是从上还是从下接近悬崖，情况都很糟糕，但幸运的是可以用使用\secref{sec:clipping_gradients}介绍的启发式\firstgls{gradient_clipping}来避免其主要缺点。
基本想法源自考虑到梯度并没有指明最佳步长，只是说明在无限小区域内的最佳方向。
当传统的梯度下降算法提议更新很大一步时，启发式\gls{gradient_clipping}会干涉去减小步长，从而使其不太可能走出梯度很大的悬崖区域。
悬崖结构在\gls{RNN}的损失函数中很常见，因为这类模型会涉及到多个时间步长因素的相乘。
因此，长期时间序列会产生大量相乘。

\subsection{\glsentrytext{long_term_dependency}}
\label{sec:long_term_dependencies}
当计算图变得非常之深时，神经网络优化算法必须克服的另一个难题出现了。
多层前馈网络会有这么深的计算图。
\chapref{chap:sequence_modeling_recurrent_and_recursive_nets}会介绍的循环网络会在很长的时间序列的每个时间点上重复应用相同的操作，因此也会有很深的计算图。
反复使用相同的参数产生了尤为突出的困难。

% -- 281 --

例如，假设某个计算图中包含一条重复与矩阵$\MW$相乘的路径。
那么$t$步后，相当于和$\MW^t$相乘。
假设$\MW$有特征值分解$\MW = \MV \text{diag}(\Vlambda) \MV^{-1}$。
在这种简单的情况下，很容易看到
\begin{equation}
  \MW^t = (\MV \text{diag}(\Vlambda) \MV^{-1})^t = \MV\text{diag}(\Vlambda)^t  \MV^{-1}.
\end{equation}
当特征值$\lambda_i$不在$1$附近时，若在量级上大于$1$则会爆炸；若小于$1$时则会消失。
\textbf{梯度消失（或弥散）问题}（\textbf{vanishing gradient problem}）和\textbf{梯度爆炸问题}（\textbf{exploding gradient problem}）是指该计算图上的梯度也会因为$\text{diag}(\Vlambda)^t$大幅度变化。
消失的梯度使得难以知道参数朝哪个方向移动能够改进损失函数，而爆炸梯度会使得学习不稳定。
之前描述的诱发梯度截断的悬崖结构便是爆炸梯度现象的一个例子。

此处描述的每个时间点重复与$\MW$相乘非常类似于寻求矩阵$\MW$的最大特征值及对应的特征向量的\firstgls{power_method}。
从这个观点来看，$\Vx^\top\MW^t$最终会丢弃$\Vx$中所有与$\MW$的主特征向量垂直的成分。

循环网络在每个时间步上使用相同的矩阵$\MW$，而前馈网络并没有。
因而即使是非常深层的前馈网络也能很大程度上避免梯度消失和爆炸问题\citep{Sussillo14}。

在循环网络已经被更详细地描述了之后，我们将会在\secref{sec:the_challenge_of_long_term_dependencies}进一步讨论循环网络训练中的挑战。

\subsection{非精确梯度}
\label{sec:inexact_gradients}
大多数优化算法的出发点都是我们知道精确的梯度或是\gls{hessian}矩阵。
在实践中，通常这些量会有\gls{noise}，甚至是有偏的估计。
几乎每一个深度学习算法都需要基于采样的估计，至少使用了小批训练样本计算梯度。

% -- 282 --

在其他情况，我们希望最小化的目标函数实际上是不可解的。
当目标函数不可解时，通常其梯度也是不可解的。
在这种情况下，我们只能近似梯度。
这些问题主要出现在第三部分中更高级的模型中。
例如，对比散度是用来近似波尔兹曼机不可解对数似然梯度的一种技术。

各种神经网络优化算法的设计都考虑到了梯度估计的欠完整性。
我们可以选择比真实损失函数更容易估计的替代损失函数来避免这个问题。

\subsection{局部和全局结构间的弱对应}
\label{sec:poor_correspondence_between_local_and_global_structure}
迄今为止，我们讨论的许多问题都是关于损失函数在单点的性质——若$J(\Vtheta)$在当前点$\Vtheta$是\gls{poor_conditioning}，或者$\Vtheta$在悬崖中，或者$\Vtheta$是一个隐藏下降梯度的\gls{saddle_points}，那么会很难更新当前步。

如果其方向在局部改进了很多，但是并没有指向损失低得多的遥远区域，那么有可能在单点处克服以上所有困难，但仍然表现不佳。

\cite{GoodfellowOptimization15}认为大部分训练的运行时间取决于到达解决方案的轨迹的长度。 
如\figref{fig:chap8_plot_atmu_relu_5}所示，学习轨迹将花费大量的时间探寻一个围绕山形结构的宽弧。

大多数优化研究的难点集中于训练是否到达了全局最小值，局部最小值，或是\gls{saddle_points}，但在实践中神经网络不会到达任何一种临界点。
\figref{fig:chap8_grad_norm_increases}表明神经网络通常不会到达梯度很小的区域。
甚至，这些临界点不是必然存在的。
例如，损失函数$-\log p(y\mid\Vx;\Vtheta)$没有全局极小点，而是当模型更自信时会逐渐趋向某个值。    
对于具有离散标签$y$和softmax分布$p(y\mid\Vx)$的分类器而言，若模型能够正确分类训练集上的每个样本，则负对数似然可以任意地趋近于零，但是不可能实际达到零值。
同样地，实值模型$p(y\mid\Vx) = \mathcal{N}(y;f(\Vtheta),\beta^{-1})$的负对数似然会趋向于负无限大——如果$f(\Vtheta)$能够正确预测所有的训练集目标$y$，学习算法会无边界地增加$\beta$。
如\figref{fig:chap8_bad_global}所示，即使没有局部极小值和\gls{saddle_points}，该例还是不能从局部优化中找到一个良好的损失函数值。

\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter8/figures/bad_global_color}}
\fi
\caption{如果局部表面没有指向全局解，基于局部下坡移动的优化可能就会失败。
这里我们提供一个例子，说明即使在没有\gls{saddle_points}或\gls{local_minima}的情况下，会如何失败。
此例中的\gls{cost_function}仅包含朝向低值而不是极小值的渐近线。
在这种情况下，困难的主要原因是初始化在``山''的错误一侧，并且无法遍历。
在高维空间中，学习算法通常可以环绕这样的高山，但是与之关联的轨迹可能会很长，并且导致过长的训练时间，如\figref{fig:chap8_plot_atmu_relu_5}所示。
}
\label{fig:chap8_bad_global}
\end{figure}


% -- 283 --

未来的研究需要进一步探索影响学习轨迹长度和更好地表征训练过程结果的因素。

许多现有研究方法在求解局部结构复杂的问题时，旨在寻求良好的初始点，而不是开发非局部范围更新的算法。

梯度下降和基本上所有有效训练神经网络的学习算法，都是基于局部较小更新。
先前的小节主要集中于为何这些局部范围更新的正确方向难以计算。
我们也许能计算目标函数的一些性质，如近似的有偏梯度或正确方向估计的方差。
在这些情况下，局部下降或许能或许不能定义到达有效解的短路径，我们并不能真的遵循局部下降的路径。
目标函数可能有诸如病态条件或不连续导数的问题，使得梯度为目标函数提供好模型的区间非常小。
在这些情况下，步长为$\epsilon$的梯度下降可能定义了一个寻求解法的合理的短路经，但是我们只能计算步长为$\delta \ll \epsilon$的局部下降方向。
在这些情况下，局部下降或许能 定义一个寻求解法的路径，但是该路径包含很多次更新，因此遵循该路径会带来很高的计算代价。
有时，目标函数有一个宽而平的区域，或是我们试图寻求精确的临界点（通常只发生于显示求解临界点的方法，如牛顿法），局部信息不能为我们提供任何指导。
在这些情况下，局部下降不能定义寻求解法的路径。
在其他情况下，局部移动可能太过贪心化，朝着梯度下降方向移动，却远离了任何解决方案，如\figref{fig:chap8_bad_global}所示，或者是沿着一个不必要的长路径到达解决方法，如\figref{fig:chap8_plot_atmu_relu_5}所示。
目前，我们还不了解这些问题中的哪一个与神经网络优化难题最相关，这是研究领域的热点方向。

% -- 284 --

不管哪个问题最重要，如果存在一个区域，我们遵循局部下降便能合理地直接到达解决方案，并且我们能够在该良好区域上初始化学习，那么这些问题都可以避免。
最后一个观点建议研究选择良好的初始点以使用传统优化算法。

\subsection{优化的理论限制}
\label{sec:theoretical_limits_of_optimization}
一些理论结果表明，我们为神经网络设计的任何优化算法都有性能限制\citep{Blum92,JuddBook,wolpert96no}。
通常这些结果不影响神经网络在实践中的应用。

一些理论结果仅适用于神经网络的单元输出离散值的情况。
然而，大多数神经网络单元输出平稳的增值，使得局部搜索求解优化可行。
一些理论结果表明，存在某类问题是不可解的，但很难判断一个特定问题是否属于该类。
其他结果表明，寻求给定规模的网络的一个解决方案是不可解的，
但在实践中，我们可以通过一个有很多对应于可接受解决方案的参数设定的更大的神经网络，很容易地找到一个解决方案。
此外，在神经网络训练中，我们通常不关注函数的精确极小值，而只关注将其值下降到足够小以获得一个很好的泛化误差。
关于优化算法能否达到这个目标的理论分析是极其困难的。
因此， 研究优化算法性能上更现实的界限仍然是机器学习研究中的一个重要目标。

% -- 285 --

\section{基本算法}
\label{sec:basic_algorithms}
之前我们已经介绍了梯度下降（\secref{sec:gradient_based_optimization}），即沿着整个训练集梯度下降的方向。
这可以使用随机梯度下降很大程度地加速，沿着随机挑选的\gls{minibatch}数据的梯度下降方向，请参看\secref{sec:stochastic_gradient_descent_chap5}和\secref{sec:batch_and_minibatch_algorithms}。

\subsection{随机梯度下降}
\label{sec:stochastic_gradient_descent_chap8}
\gls{SGD}（SGD）及其变种很可能是一般机器学习中用得最多的优化算法，特别是在深度学习中。
如\secref{sec:batch_and_minibatch_algorithms}讨论，通过计算独立同分布地从数据生成分布中抽取的$m$个\gls{minibatch}样本的梯度均值，我们可以得到梯度的无偏估计。

\algref{alg:sgd}展示了如何使用这个下降梯度的估计。
\begin{algorithm}[ht]
\caption{\gls{SGD}(\glssymbol{SGD})在第$k$个训练迭代的更新}
\label{alg:sgd}
\begin{algorithmic}
\REQUIRE \gls{learning_rate} $\epsilon_k$
\REQUIRE 初始参数$\Vtheta$
\WHILE{没有达到停止\gls{criterion}}
    \STATE 从训练集中采包含$m$个样本$\{ \Vx^{(1)},\dots, \Vx^{(m)}\}$ 的\gls{minibatch}，对应目标为$\Vy^{(i)}$。
    \STATE 计算梯度估计： $\hat{\Vg} \leftarrow + 
         \frac{1}{m} \nabla_{\Vtheta} \sum_i L(f(\Vx^{(i)};\Vtheta),\Vy^{(i)})$
    \STATE 应用更新：$\Vtheta \leftarrow \Vtheta - \epsilon \hat{\Vg}$
\ENDWHILE
\end{algorithmic}
\end{algorithm}


\glssymbol{SGD}算法中的一个关键参数是学习速率。
之前，我们介绍的\glssymbol{SGD}使用固定的学习速率。
在实践中，有必要随着时间的推移逐渐降低学习速率，因此我们将第$k$步迭代的学习速率记作$\epsilon_k$。

这是因为\glssymbol{SGD}梯度估计引入的噪源（$m$个训练样本的随机采样）并不会在极小值处消失。
相比之下，当我们使用\gls{batch}梯度下降到达极小值时，整个损失函数的真实梯度会变得很小，甚至为$\mathbf{0}$，因此\gls{batch}梯度下降可以使用固定的学习速率。
保证\glssymbol{SGD}收敛的一个充分条件是
\begin{equation}
\label{eq:8.12}
    \sum_{k=1}^\infty \epsilon_k = \infty,
\end{equation}
且
\begin{equation}
\label{eq:8.13}
    \sum_{k=1}^\infty \epsilon_k^2 < \infty.
\end{equation}

% -- 286 --

实践中，一般会线性衰减学习速率到第$\tau$次迭代：
\begin{equation}
\label{eq:8.14}
    \epsilon_k = (1-\alpha) \epsilon_0 + \alpha \epsilon_\tau
\end{equation}
其中$\alpha = \frac{k}{\tau}$。
在$\tau$步迭代之后，一般使$\epsilon$保持常数。

学习速率可通过试验和误差来选取，通常最好的选择方法是画出目标函数值随时间变化的学习曲线。
与其说是科学，这更是一门艺术，关于这个问题的大多数指导都应该被怀疑地看待。
使用线性时间表时，参数选择为$\epsilon_0$，$\epsilon_\tau$，$\tau$。  
通常$\tau$被设为需要反复遍历训练样本几百次的迭代次数。
通常$\epsilon_\tau$应设为大约$1\%$的$\epsilon_0$。
主要问题是如何设置$\epsilon_0$。
若$\epsilon_0$太大，学习曲线将会剧烈振荡，损失函数值通常会明显增加。
温和的振荡是良好的，特别是训练于随机损失函数上，例如由信号丢失引起的损失函数。
如果学习速率太慢，那么学习进程会缓慢。
如果初始学习速率太低，那么学习可能会卡在一个相当高的损失值。
通常，就总训练时间和最终损失值而言，最优初始学习速率会高于大约迭代100步后输出最好效果的学习速率。
因此，通常最好是检测最早的几轮迭代，使用一个高于此时效果最佳学习速率的学习速率，但又不能太高以致严重的不稳定性。  

\glssymbol{SGD}和相关的\gls{minibatch}或在线基于梯度的优化的最重要的性质是每一步更新的计算时间不会随着训练样本数目而增加。
即使训练样本数目非常大时，这也能收敛。
对于足够大的数据集，\glssymbol{SGD}可能会在处理整个训练集之前就收敛到最终测试集误差的某个固定容差范围内。

研究优化算法的收敛率，一般会衡量\firstgls{excess_error}$J(\Vtheta) - \min_{\Vtheta} J(\Vtheta)$，即当前损失函数超出最低可能损失的量。
\glssymbol{SGD}应用于凸问题时，$k$步迭代后的额外误差量级是$O(\frac{1}{\sqrt{k}})$，在强凸情况下是$O(\frac{1}{k})$。
除非假定额外的条件，否则这些界限不能进一步改进。
\gls{batch}梯度下降在理论上比随机梯度下降有更好的收敛率。
然而，Cram\'er-Rao界限\citep{Cramer-1946,Rao-1945}指出，泛化误差的下降速度不会快于$O(\frac{1}{k})$。
\cite{bottou-bousquet-2008-small}由此认为对于机器学习任务，不值得探寻收敛快于$O(\frac{1}{k})$的优化算法——更快的收敛可能对应着过拟合。
此外，渐近分析掩盖了随机梯度下降在少量更新步之后的很多优点。
对于大数据集，SGD初始快速更新只需非常少量样本计算梯度的能力远远超过了其缓慢的渐近收敛。
本章剩余部分介绍的大多数算法都实现了实践中有用的好处，但是丢失了常数倍$O(\frac{1}{k})$的渐近分析。
我们也可以权衡\gls{batch}梯度下降和\gls{SGD}两者的优点，在学习过程中逐渐增大\gls{minibatch}的大小。

% -- 287 --

了解\glssymbol{SGD}更多的信息，请参看\cite{Bottou98}。

\subsection{动量}
\label{sec:momentum}
虽然随机梯度下降仍然是非常受欢迎的优化方法，但学习速率有时会很慢。
动量方法\citep{polyak1964some}旨在加速学习，特别是处理高曲率，小但一致的梯度，或是带\gls{noise}的梯度。
动量算法积累了之前梯度指数级衰减的移动平均，并且继续沿该方向移动。
动量的效果如\figref{fig:chap8_momentum}所示。

\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter8/figures/momentum_color}}
\fi
\caption{\gls{momentum}的主要目的是解决两个问题：\gls{hessian}矩阵的不良条件数和随机梯度的方差。 
我们通过此图说明\gls{momentum}如何克服这两个问题的第一个。
轮廓线描绘了一个二次\gls{loss_function}（具有不良条件数的\gls{hessian}矩阵）。
横跨轮廓的红色路径表示\gls{momentum}学习规则所遵循的路径，它使该函数最小化。
我们在每个步骤画一个箭头，指示梯度下降将在该点采取的步骤。
我们可以看到，一个条件数较差的二次\gls{objective_function}看起来像一个长而窄的山谷或陡峭的峡谷。
\gls{momentum}正确地纵向穿过峡谷，而梯度步骤则会浪费时间在峡谷的窄轴上来回移动。
比较\figref{fig:chap4_poor_conditioning_color}，它也显示了没有\gls{momentum}的梯度下降的行为。
}
\label{fig:chap8_momentum}
\end{figure}

从形式上看，动量算法引入了变量$\Vv$充当速度的角色——它代表参数在参数空间移动的方向和速度。
速度被设为负梯度的指数衰减平均。
名称\firstgls{momentum}来自物理类比，根据牛顿运动定律，负梯度是移动参数空间中粒子的力。
动量在物理学上是质量乘以时间。
在动量学习算法中，我们假设是单位质量，因此速度向量$\Vv$也可以看作是粒子的动量。
超参数$\alpha\in[0,1)$决定了之前梯度的贡献衰减得有多快。
更新规则如下：
\begin{equation}
\Vv \leftarrow \alpha \Vv - \epsilon \nabla_{\Vtheta} \left( \frac{1}{m} \sum_{i=1}^m  L(\Vf(\Vx^{(i)}; \Vtheta), \Vy^{(i)}   )  \right),
\end{equation}
\begin{equation}
\Vtheta \leftarrow \Vtheta  + \Vv .
\end{equation}
速度$\Vv$累积了梯度元素$\nabla_{\Vtheta}( \frac{1}{m} \sum_{i=1}^m L( \Vf(\Vx^{(i)}; \Vtheta), \Vy^{(i)} )  )$。
相对于$\epsilon$的$\alpha$越大，之前梯度对现在方向的影响也越大。
带动量的\glssymbol{SGD}算法如\algref{alg:momentum}所示。

\begin{algorithm}[ht]
\caption{使用\gls{momentum}的\gls{SGD}(\glssymbol{SGD})}
\label{alg:momentum}
\begin{algorithmic}
\REQUIRE \gls{learning_rate} $\epsilon$， \gls{momentum}参数 $\alpha$
\REQUIRE 初始参数 $\Vtheta$，初始速度 $\Vv$
\WHILE{没有达到停止\gls{criterion}}
    \STATE 从训练集中采包含$m$个样本$\{ \Vx^{(1)},\dots, \Vx^{(m)}\}$ 的\gls{minibatch}，对应目标为$\Vy^{(i)}$。
    \STATE 计算梯度估计：$\Vg \leftarrow 
         \frac{1}{m} \nabla_{\Vtheta} \sum_i L(f(\Vx^{(i)};\Vtheta),\Vy^{(i)})$
    \STATE  计算速度更新：$\Vv \leftarrow \alpha \Vv - 
    \epsilon \Vg$
    \STATE 应用更新：$\Vtheta \leftarrow \Vtheta + \Vv$ 
\ENDWHILE
\end{algorithmic}
\end{algorithm}


% -- 288 --

之前，步长只是梯度范数乘以学习率。
现在，步长取决于梯度序列的大小和排列。
当许多连续的梯度指向相同的方向时，步长最大。
如果动量算法总是观测到梯度$\Vg$，那么它会在方向$-g$上不停加速，直到达到最后速度的步长为
\begin{equation}
    \frac{\epsilon \norm{\Vg}}{1-\alpha} .
\end{equation}
将动量的超参数视为$\frac{1}{1-\alpha}$有助于理解。
例如，$\alpha=0.9$对应着最大速度$10$倍于梯度下降算法。

% -- 289 --

在实践中，$\alpha$的一般取值为$0.5$，$0.9$和$0.99$。
和学习速率一样，$\alpha$也会随着时间变化。 
一般初始值是一个较小的值，随后会慢慢变大。
随着时间推移改变$\alpha$没有收缩$\epsilon$更重要。

我们可以将动量算法视为模拟连续时间下牛顿动力学下的粒子。
这种物理类比有助于直觉上理解动量和梯度下降算法是如何表现的。

粒子在任意时间点的位置由$\Vtheta(t)$给定。
粒子会受到净力$\Vf(t)$。
该力会导致粒子加速：
\begin{equation}
    \Vf(t) = \frac{\partial^2}{\partial t^2} \Vtheta(t) .
\end{equation}
与其将其视为位置的二阶微分方程，我们不如引入表示粒子在时间$t$处速度的变量$\Vv(t)$，将牛顿动力学重写为一阶微分方程：
\begin{equation}
    \Vv(t) = \frac{\partial}{\partial t} \Vtheta(t) ,
\end{equation}
\begin{equation}
    \Vf(t) = \frac{\partial}{\partial t} \Vv(t) .
\end{equation}
由此，动量算法包括由数值模拟求解微分方程。
求解微分方程的一个简单数值方法是欧拉方法，通过在每个梯度方向上小且有限的步来简单模拟该等式定义的动力学。

这解释了动量更新的基本形式，但具体什么是力呢？
力正比于损失函数的负梯度$-\nabla_{\Vtheta} J(\Vtheta)$。
该力推动粒子沿着损失函数表面下坡的方向移动。
梯度下降算法基于每个梯度简单地更新一步，而使用动量算法的牛顿方案则使用该力改变粒子的速度。
我们可以将粒子视作在冰面上滑行的冰球。
每当它沿着表面最陡的部分下降时，它会累积继续在该方向上滑行的速度，直到其开始向上滑动为止。

% -- 290 --

另一个力也是必要的。
如果损失函数的梯度是唯一的力，那么粒子可能永远不会停下来。
想象一下，假设冰面没有摩擦，一个冰球从山谷的一端下滑，上升到另一端，永远来回振荡。
要解决这个问题，我们添加另一个正比于$-\Vv(t)$的力。
在物理术语中，此力对应于粘性阻力，就像粒子必须通过一个抵抗介质，如糖浆。
这会导致粒子随着时间推移逐渐失去能量，最终收敛到局部极小值。

为什么要特别使用$-\Vv(t)$和粘性阻力呢？
部分原因是因为$-\Vv(t)$在数学上的便利——速度的整数幂很容易处理。
然而，其他物理系统具有基于速度的其他整数幂的其他类型的阻力。
例如，颗粒通过空气时会受到正比于速度平方的湍流阻力，而颗粒沿着地面移动时会受到恒定大小的摩擦力。
这些选择都不合适。
湍流阻力，正比于速度的平方，在速度很小时会很弱。
不够强到使粒子停下来。
非零值初始速度的粒子仅受到湍流阻力，会从初始位置永远地移动下去，和初始位置的距离大概正比于$O(\log t)$。
因此我们必须使用速度较低幂次的力。
如果幂次为零，相当于干摩擦，那么力太强了。
当损失函数的梯度表示的力很小但非零时，由于摩擦导致的恒力会使得粒子在达到局部极小值之前就停下来。
粘性阻力避免了这两个问题——它足够弱，可以使梯度引起的运动直到达到最小，但又足够强，使得坡度不够时可以阻止运动。

\subsection{Nesterov动量}
\label{sec:nesterov_momentum}
受Nesterov加速梯度算法\citep{Nesterov83b,Nesterov03}启发，\cite{sutskeverimportance}提出了动量算法的一个变种。
这种情况的更新规则如下：
\begin{equation}
    \Vv \leftarrow \alpha\Vv - \epsilon \nabla_{\Vtheta} \left[
    \frac{1}{m} \sum_{i=1}^m L( \Vf(\Vx^{(i)}; \Vtheta + \alpha \Vv), \Vy^{(i)} )
 \right],
\end{equation}
\begin{equation}
    \Vtheta \leftarrow \Vtheta + \Vv ,
\end{equation}
其中参数$\alpha$和$\epsilon$发挥了和标准动量方法中类似的作用。 
Nesterov动量和标准动量之间的区别体现在梯度计算上。
Nesterov动量中，梯度计算在施加当前速度之后。
因此，Nesterov动量可以解释为往标准动量方法中添加了一个\emph{校正因子}。
完整的Nesterov动量算法如\algref{alg:nesterov}所示。


\begin{algorithm}[ht]
\caption{使用Nesterov\gls{momentum}的\gls{SGD}(\glssymbol{SGD})}
\label{alg:nesterov}
\begin{algorithmic}
\REQUIRE  \gls{learning_rate} $\epsilon$， \gls{momentum}参数 $\alpha$
\REQUIRE 初始参数 $\Vtheta$，初始速度 $\Vv$
\WHILE{没有达到停止\gls{criterion}}
    \STATE 从训练集中采包含$m$个样本$\{ \Vx^{(1)},\dots, \Vx^{(m)}\}$ 的\gls{minibatch}，对应目标为$\Vy^{(i)}$。
    \STATE 应用临时更新： $\tilde{\Vtheta} \leftarrow \Vtheta  + \alpha \Vv$
         \STATE 计算梯度（在临时点）：$\Vg \leftarrow 
         \frac{1}{m} \nabla_{\tilde{\Vtheta}} \sum_i L(f(\Vx^{(i)};\tilde{\Vtheta}),\Vy^{(i)})$
    \STATE 计算速度更新：$\Vv \leftarrow \alpha \Vv - 
    \epsilon \Vg$
    \STATE 应用更新：$\Vtheta \leftarrow \Vtheta + \Vv$ 
\ENDWHILE
\end{algorithmic}
\end{algorithm}



% -- 291 --

在凸\gls{batch}梯度的情况下，Nesterov动量将额外误差收敛率从$O(1/k)$（$k$步后）改进到$O(1/k^2)$，如\cite{Nesterov83b}所示。
不幸的是，在随机梯度的情况下，Nesterov动量没有改进收敛率。

\section{参数初始化策略}
\label{sec:parameter_initialization_strategies}
有些优化算法本质上是非迭代的，只是求解一个解点。
其他有些优化算法本质上是迭代的，但是应用于这一类的优化问题时，能和初始值无关地在可接受的时间内收敛到可接受的解。
深度学习训练算法通常没有这两种奢侈的性质。
深度学习模型的训练算法通常是迭代的，因此要求使用者指定一些开始迭代的初始点。
此外，训练\gls{deep_model}是一个足够困难的问题，以至于大多数算法都很大程度地受到初始化选择的影响。
初始点能够决定算法是否收敛，有些初始点十分不稳定，使得该算法会遭遇数值困难，并完全失败。
当学习收敛时，初始点可以决定学习收敛得多块，以及是否收敛到一个损失高或低的点。
此外，差不多损失的点可以具有区别极大的泛化误差，初始点也可以影响泛化。

% -- 292 --

现代的初始化策略是简单的，启发式的。
设定改进的初始化策略是一项困难的任务，因为神经网络优化至今还未被很好理解。
大多数初始化策略基于在神经网络初始化时实现一些很好的性质。
然而，我们并没有很好地理解这些性质中的哪些会在学习开始进行后的哪些情况下得以保持。
进一步的难点是，有些初始点从优化的观点看或许是有利的，但是从泛化的观点看是不利的。
我们对于初始点如何影响泛化的理解是相当原始的，几乎没有提供如何选择初始点的任何指导。

也许完全确知的唯一特性是初始参数需要在不同单元间``破坏对称性''。
如果具有相同激励函数的两个\gls{hidden_unit}连接到相同的输入，那么这些单元必须具有不同的初始参数。
如果它们具有相同的初始参数，然后应用到确定性损失和模型的确定性学习算法将一直以相同的方式更新这两个单元。
即使模型或训练算法能够使用随机性为不同的单元计算不同的更新（例如具备信息丢失的训练），通常来说，最好还是初始化每个单元使其和其他单元计算不同的函数。
这或许有助于确保没有输入模式丢失在前向传播的零空间中，没有梯度模式丢失在反向传播的零空间中。
每个单元计算不同函数的目标促使了参数的随机初始化。
我们可以明确地搜索一大组彼此互不相同的基函数，但这经常会导致明显的计算代价。  
例如，如果我们有和输出一样多的输入，我们可以使用Gram-Schmidt正交化于初始的权重矩阵，保证每个单元计算彼此非常不同的函数。
在高维空间上使用高熵分布来随机初始化，计算代价小并且不太可能分配单元计算彼此相同的函数。

通常情况下，我们可以为每个单元的\gls{bias_aff}设置启发式挑选的常数，仅随机初始化权重。
额外的参数——例如编码预测条件方差的参数——通常和偏差一样设置为启发式选择的常数。

我们几乎总是初始化模型的权重为高斯或均匀分布中随机抽取的值。
高斯或均匀分布的选择似乎不会有很大的差别，但也没有被详尽地研究。
然而，初始分布的大小确实对优化过程的结果和网络泛化能力都有很大的影响。

% -- 293 --

更大的初始权重具有更强的破坏对称性的作用，有助于避免冗余的单元。
它们也有助于避免在每层线性成分的前向或反向传播中丢失信号——矩阵中更大的值在矩阵乘法中有更大的输出。
如果初始权重太大，那么会在前向传播或反向传播中产生爆炸的值。
在循环网络中，很大的权重也可能导致\firstgls{chaos}（对于输入中很小的扰动非常敏感，导致确定性前向传播过程表现随机）。
在一定程度上，梯度爆炸问题可以通过梯度截断来缓解（执行梯度下降步骤之前设置梯度的阈值）。
较大的权重也会产生使得激励函数饱和的值，导致饱和单元的梯度完全丢失。
这些竞争因素决定了权重的理想初始大小。

关于如何初始化网络，正则化和优化有非常不同的视角。
优化视角建议权重应该足够大以成功传播信息，但是正则化希望其小一点。
诸如随机梯度下降这类对权重较小的增量更新，趋于停止在更靠近的初始参数的区域（不管是由于卡在低梯度的区域，还是由于触发了基于过拟合 的提前停止准则）的优化算法倾向于最终参数应接近于初始参数。
回顾\secref{sec:early_stopping}，在某些模型上，提前停止的梯度下降等价于权重衰减。
在一般情况下，提前停止的梯度下降和权重衰减不同，但是提供了一个宽松的类比去考虑初始化的影响。
我们可以将初始化参数$\Vtheta$为$\Vtheta_0$类比于强置均值为$\Vtheta_0$的高斯先验$p(\Vtheta)$。
从这个角度来看，选择$\Vtheta_0$接近$0$是有道理的。
这个先验表明，单元间彼此互不交互比交互更有可能。
只有在目标方程的似然项表达出对交互很强的偏好时，单元才会交互。
另一方面，如果我们初始化$\Vtheta_0$为很大的值，那么我们的先验指定了哪些单元应互相交互，以及它们应如何交互。

有些启发式方法可用于选择权重的初始大小。
一种初始化$m$个输入和$n$输出的全连接层的权重的启发式方法是从分布$U(-\frac{1}{\sqrt{m}}, \frac{1}{\sqrt{m}})$中采样权重，
而\cite{Glorot+al-AI-2011-small}建议使用\firstgls{normalized_initialization}
\begin{equation}
    W_{i,j} \sim U \left(-\sqrt{\frac{6}{m+n}}, \sqrt{\frac{6}{m+n}}\right) .
\end{equation}
这后一种启发式方法初始化所有的层，折衷于使其具有相同激励方差和使其具有相同梯度方差之间。
该式由不含非线性的链式矩阵乘法网络的假设推导得出。
现实的神经网络显然会违反这个假设，但很多设计于线性模型的策略在其非线性对应中效果也不错。

% -- 294 --

\cite{Saxe-et-al-ICLR13}建议初始化随机正交矩阵，仔细挑选负责每一层非线性缩放或\textbf{增益}（\textbf{gain}）因子$g$。
他们得到了用于不同类型非线性激励函数的特定缩放因子。
这种初始化方案也是受启发于不含非线性的矩阵相乘序列的\gls{deep_network}。
在该模型下，这个初始化方案保证了达到收敛所需的训练迭代总数独立于深度。

增加缩放因子$g$将网络推向网络前向传播时激励范数增加，反向传播时梯度范数增加的区域。
\cite{Sussillo14}表明，正确设置缩放因子足以训练深达$1000$层的网络，不需要使用正交初始化。
这种方法的一个重要观点是，在前馈网络中，激励和梯度会在每一步前向或反向传播中增加或缩小，遵循随机游动行为。
这是因为前馈网络在每一层使用了不同的权重矩阵。
如果该随机游动调整到保持范数，那么前馈网络能够很大程度地避免相同权重矩阵用于每层的梯度消失和爆炸问题，如\secref{sec:long_term_dependencies}所述。

不幸的是，这些初始权权重的最佳准则往往不会带来最佳效果。
这可能有三种不同的原因。
首先，我们可能使用了错误的标准——它实际上并不能有利于保持整个网络信号的范数。
其次，初始化时强加的性质可能在学习开始进行后不能保持。
最后，该标准可能成功提高了优化速度，但意外地增大了泛化误差。
在实践中，我们通常需要将权重范围视为超参数，其最优值大致接近，但并不完全等于理论预测。

% -- 295 --

数值范围准则的一个缺点是，设置所有的初始权重具有相同的标准差，例如$\frac{1}{\sqrt{m}}$，会使得层很大时每个单一权重会变得极其小。
\cite{martens2010hessian-small}提出了一种被称为\firstgls{sparse_initialization}的替代方案，每个单元初始化为恰好有$k$个非零权重。
这个想法保持该单元输入的总数量独立于输入数目$m$，而不使单一权重元素的大小随$m$缩小。
稀疏初始化有助于实现单元之间在初始化时更具多样性。
但是，它也非常偏好于具有很大高斯值的权重。
因为梯度下降需要很长时间缩小``不正确''的大值，这个初始化方案可能会导致单元问题，例如\gls{maxout}单元有几个过滤器，必须互相之间仔细调整。

计算资源允许的话，将每层权重的初始数值范围设为超参数通常是个好主意，使用\secref{sec:automatic_hyperparameter_optimization_algorithms}介绍的超参数搜索算法，如随机搜索，挑选这些数值范围。
是否选择使用密集或稀疏初始化也可以设为一个超参数。
替代地，我们可以手动搜索最优初始范围。
一个好的挑选初始数值范围的经验法则是观测单个\gls{minibatch}数据上的激励或梯度的范围或标准差。
如果权重太小，那么当激励值在\gls{minibatch}上前向传播于网络时，激励值的范围会缩小。
通过重复识别具有不可接受的激励小值的第一层，并提高其权重，最终有可能得到一个全部都是合理初始激励的网络。
如果学习在这点上仍然很慢，观测下梯度的范围或标准差可能也会有所帮助。
这个过程原则上是自动的，且通常计算量低于基于验证集误差的超参数优化，因为它是基于初始模型在单批数据上的行为反馈，而不是在验证集上训练模型的反馈。
由于这个协议很长时间都被启发式使用，最近\cite{mishkin2015all}更正式地确定，研究了该协议。

目前为止，我们关注在权重的初始化上。
幸运的是，其他参数的初始化通常更容易。

% -- 296 --

设置\gls{bias_aff}的方法必须和设置权重的方法协调。
设置\gls{bias_aff}为零通常在大多数权重初始化方案中是可行的。
有些我们可能设置\gls{bias_aff}为非零值的情况：
\begin{itemize}
\item 如果\gls{bias_aff}是作为输出单元，那么初始化\gls{bias_aff}以获取正确的输出边缘统计通常是有利的。
要做到这一点，我们假设初始权重足够小，该单元的输出仅由\gls{bias_aff}决定。
这说明设置\gls{bias_aff}为应用于训练集上输出边缘统计的激励函数的逆。
例如，如果输出是类上的分布，且该分布是高度偏态分布，第$i$类的边缘概率由某个向量$\Vc$的第$i$个元素给定，那么我们可以通过求解方程$\text{softmax}(\Vb)=\Vc$来设置偏置向量$\Vb$。
这不仅适用于分类器，也适用于我们将在第III部分遇到的模型，例如\gls{AE}和波尔兹曼机。
这些模型拥有输出类似于输入数据$\Vx$的网络层，非常有助于初始化这些层的偏置以匹配$\Vx$上的边缘分布。

\item 有时，我们可能想要选择\gls{bias_aff}以避免初始化引起太大饱和。
例如，我们可能会将ReLU的\gls{hidden_unit}设为$0.1$而非$0$，以避免ReLU在初始化时饱和。
尽管这种方法不符合不希望偏置具有很强输入的权重初始化准则。
例如，不建议使用随机游走初始化\citep{Sussillo14}。

\item 有时，一个单元会控制其他单元能否参与到方程中。
在这种情况下，我们有一个单元输出$u$，另一个单元$h\in[0,1]$，那么我们可以将$h$视作闸门，以决定$uh\approx 1$还是$uh\approx 0$。
在这种情形下，我们希望设置\gls{bias_aff}$h$，使得在初始化的大多数情况下$h\approx 1$。
否则，$u$没有机会学习。
例如，\cite{Jozefowicz-et-al-ICML2015}提议设置LSTM模型遗忘门的\gls{bias_aff}为$1$，如\secref{sec:the_long_short_term_memory_and_other_gated_rnns}所述。
\end{itemize}

另一种常见类型的参数是方差或精确度参数。
例如，我们用以下模型进行带条件方差估计的线性回归
\begin{equation}
    p(y\mid\Vx) = \mathcal{N} (y \mid \Vw^\top \Vx + b, 1/\beta) ,
\end{equation}
其中$\beta$是精确度参数。
通常我们能安全地初始化方差或精确度参数为$1$。
另一种方法假设初始权重足够接近零，设置偏置可以忽略权重的影响，然后设定偏置以产生输出的正确边缘均值，并设置训练集输出的边缘方差的方差参数。

% -- 297 --

除了这些初始化模型参数的简单固定或随机方法，还有可能使用机器学习初始化模型参数。
本书第III部分讨论的常用技巧是初始化监督模型的参数为无监督模型训练于相同的输入上学习出的参数。
我们也可以在相关问题上使用监督训练。
即使是运行监督训练在一个不相关的任务上，有时也能得到一个比随机初始化具有更快收敛率的初始值。
这些初始化技巧有些能够得到更快的收敛率和更好的泛化误差，因为它们编码了模型初始参数分布的信息。
其他技巧显然效果不错的原因主要在于它们设置参数为正确的数值范围，或是设置不同单元计算互相不同的函数。

\section{自适应学习率的算法}
\label{sec:algorithms_with_adaptive_learning_rates}
神经网络研究员早就意识到学习率肯定是难以设置的超参数之一，因为它对模型的性能有显著的影响。
正如我们在\secref{sec:gradient_based_optimization}和\secref{sec:challenges_in_neural_network_optimization}中探讨的，损失通常高度敏感于参数空间中的某些方向，而不敏感于其他。
动量算法可以在一定程度缓解这些问题，但这样做的代价是引入了另一个超参数。
在这种情况下，自然会问有没有其他方法。
如果我们相信方向敏感度有些轴对齐，那么每个参数设置不同的学习率，在整个学习过程中自动适应这些学习率便是有道理的。

\textbf{delta-bar-delta}算法\citep{jacobs1988}是一个早期的在训练时适应模型参数单独学习速率的启发式方法。
该方法基于一个很简单的想法，如果损失对于某个给定模型参数的偏导保持相同的符号，那么学习速率应该增加。如果对于该参数的偏导变化了符号，那么学习率应减小。
当然，这种方法只能应用于全\gls{batch}优化中。

最近，一些增量（或者基于\gls{minibatch}）的算法被提出适应模型参数的学习率。
这节将简要回顾一些这种算法。

% -- 298 --

\subsection{AdaGrad}
\label{sec:adagrad}
\textbf{AdaGrad}算法，如\algref{alg:ada_grad}所示，独立地适应所有模型参数的学习速率，放缩每个参数反比于其所有梯度历史平方值总和的平方根\citep{Duchi+al-2011}。
具有损失最大偏导的参数相应地有一个快速下降的学习速率，而具有小偏导的参数在学习速率上有相对较小的下降。
净效果是在参数空间中更为平缓的倾斜方向会取得更大的进步。

在凸优化背景中，AdaGrad算法具有一些令人满意的理论性质。
然而，经验上已经发现，对于训练\gls{DNN}模型而言，\emph{从训练开始时}积累梯度平方会导致有效学习速率过早和过量的减小。
AdaGrad在某些深度学习模型上效果不错，但不是全部。


\begin{algorithm}[ht]
\caption{AdaGrad算法}
\label{alg:ada_grad}
\begin{algorithmic}
\REQUIRE 全局\gls{learning_rate} $\epsilon$
\REQUIRE 初始参数$\Vtheta$
\REQUIRE 小常数$\delta$，为了数值稳定大约设为$10^{-7}$
\STATE 初始化梯度累积变量$\Vr = 0$
\WHILE{没有达到停止\gls{criterion}}
    \STATE 从训练集中采包含$m$个样本$\{ \Vx^{(1)},\dots, \Vx^{(m)}\}$ 的\gls{minibatch}，对应目标为$\Vy^{(i)}$。
    \STATE 计算梯度： $\Vg \leftarrow  
         \frac{1}{m} \nabla_{\Vtheta} \sum_i L(f(\Vx^{(i)};\Vtheta),\Vy^{(i)})$ 
    \STATE 累积平方梯度：$\Vr \leftarrow \Vr + \Vg \odot \Vg$
    \STATE 计算更新：$\Delta \Vtheta \leftarrow -
    \frac{\epsilon}{\delta+ \sqrt{\Vr}} \odot\Vg$  \ \  （逐元素地应用除和求平方根）
    \STATE 应用更新：$\Vtheta \leftarrow \Vtheta + \Delta \Vtheta$
\ENDWHILE
\end{algorithmic}
\end{algorithm}


\subsection{RMSProp}
\label{sec:rmsprop}
\textbf{RMSProp}算法\citep{Hinton-ipam2012}修改AdaGrad以在非凸设定下效果更好，改变梯度积累为指数加权的移动均值。
AdaGrad旨在应用于凸问题时快速收敛。
当应用于非凸函数训练神经网络时，学习轨迹可能穿过了很多不同的结构，最终到达一个局部是凸碗的区域。
AdaGrad根据平方梯度的整个历史收缩学习率，可能使得学习率在达到这样的凸结构前就变得太小了。
RMSProp使用指数衰减平均以丢弃遥远过去的历史，使其能够在找到凸碗状结构后快速收敛，
它就像一个初始化于该碗状结构的AdaGrad算法实例。

% -- 299 --

RMSProp的标准形式如\algref{alg:rms_prop}所示，结合Nesterov动量的形式如\algref{alg:rms_nesterov}所示。
相比于AdaGrad，使用移动均值引入了一个新的超参数$\rho$，控制移动平均的长度范围。

% -- 300 --

经验上，RMSProp已被证明是一种有效且实用的\gls{DNN}优化算法。
目前它是深度学习从业者经常采用的优化方法之一。


\begin{algorithm}[ht]
\caption{RMSProp算法}
\label{alg:rms_prop}
\begin{algorithmic}
\REQUIRE 全局\gls{learning_rate} $\epsilon$，衰减速率$\rho$
\REQUIRE  初始参数$\Vtheta$
\REQUIRE 小常数$\delta$，通常设为$10^{-6}$（用于被小数除时的数值稳定）
\STATE 初始化累积变量 $\Vr = 0$
\WHILE{没有达到停止\gls{criterion}}
    \STATE 从训练集中采包含$m$个样本$\{ \Vx^{(1)},\dots, \Vx^{(m)}\}$ 的\gls{minibatch}，对应目标为$\Vy^{(i)}$。
    \STATE 计算梯度：$\Vg \leftarrow  
         \frac{1}{m} \nabla_{\Vtheta} \sum_i L(f(\Vx^{(i)};\Vtheta),\Vy^{(i)})$ 
    \STATE 累积平方梯度：$\Vr \leftarrow \rho
    \Vr + (1-\rho) \Vg \odot \Vg$
    \STATE 计算参数更新：$\Delta \Vtheta =
    -\frac{\epsilon}{\sqrt{\delta + \Vr}} \odot \Vg$  \ \  ($\frac{1}{\sqrt{\delta + \Vr}}$ 逐元素应用)
    \STATE 应用更新：$\Vtheta \leftarrow \Vtheta + \Delta \Vtheta$
\ENDWHILE
\end{algorithmic}
\end{algorithm}

\begin{algorithm}[ht]
\caption{使用Nesterov\gls{momentum}的RMSProp算法}
\label{alg:rms_nesterov}
\begin{algorithmic}
\REQUIRE 全局\gls{learning_rate} $\epsilon$，衰减速率$\rho$， \gls{momentum}系数$\alpha$
\REQUIRE 初始参数$\Vtheta$，初始参数$\Vv$
\STATE 初始化累积变量 $\Vr = 0$
\WHILE{没有达到停止\gls{criterion}} % NOTE: do not capitalize the condition
    \STATE 从训练集中采包含$m$个样本$\{ \Vx^{(1)},\dots, \Vx^{(m)}\}$ 的\gls{minibatch}，对应目标为$\Vy^{(i)}$。
    \STATE 计算临时更新：$\tilde{\Vtheta} \leftarrow \Vtheta + \alpha \Vv$
    \STATE 计算梯度：$\Vg \leftarrow  
         \frac{1}{m} \nabla_{\tilde{\Vtheta}} \sum_i L(f(\Vx^{(i)};\tilde{\Vtheta}),\Vy^{(i)})$ 
    \STATE  累积梯度：$\Vr \leftarrow \rho
    \Vr + (1-\rho) \Vg \odot \Vg$
    \STATE  计算速度更新：$\Vv \leftarrow \alpha \Vv
    -\frac{\epsilon}{\sqrt{\Vr}} \odot \Vg$ \ \  ($\frac{1}{\sqrt{\Vr}}$ 逐元素应用)
    \STATE 应用更新：$\Vtheta \leftarrow \Vtheta + \Vv$
\ENDWHILE
\end{algorithmic}
\end{algorithm}


\subsection{Adam}
\label{sec:adam}
\textbf{Adam}\citep{kingma2014adam}是另一种学习率自适应的优化算法，如\algref{alg:adam}所示。
``Adam''这个名字派生自短语``Adaptive moments''。
早期算法背景下，它也许最好被看作结合RMSProp和具有一些重要区别的动量的变种。
首先，在Adam中，动量直接并入了梯度一阶矩（带指数加权）的估计。
将动量加入RMSProp最直观的方法是应用动量于缩放后的梯度。
结合重放缩的动量使用没有明确的理论动机。
其次，Adam包括负责原点初始化的一阶矩（动量项）和（非中心的）二阶矩的估计修正偏置（\algref{alg:adam}）。
RMSProp也采用了（非中心的）二阶矩估计，然而缺失了修正因子。
因此，不像Adam，RMSProp二阶矩估计可能在训练初期有很高的偏置。
Adam通常被认为对超参数的选择相当鲁棒，尽管学习速率有时需要从建议的默认修改。

\begin{algorithm}[ht]
\caption{Adam算法}
\label{alg:adam}
\begin{algorithmic}
\REQUIRE 步长 $\epsilon$ （建议默认为： $0.001$）
\REQUIRE 矩估计的指数衰减速率， $\rho_1$ 和 $\rho_2$ 在区间 $[0, 1)$内。
（建议默认为：分别为$0.9$ 和 $0.999$）
\REQUIRE 用于数值稳定的小常数 $\delta$  （建议默认为： $10^{-8}$）
\REQUIRE 初始参数 $\Vtheta$
\STATE 初始化一阶和二阶矩变量 $\Vs = 0 $, $\Vr = 0$
\STATE 初始化\gls{time_step} $t=0$ 
\WHILE{没有达到停止\gls{criterion}}
    \STATE 从训练集中采包含$m$个样本$\{ \Vx^{(1)},\dots, \Vx^{(m)}\}$ 的\gls{minibatch}，对应目标为$\Vy^{(i)}$。
    \STATE 计算梯度：$\Vg \leftarrow \frac{1}{m} \nabla_{\Vtheta} \sum_i L(f(\Vx^{(i)};\Vtheta),\Vy^{(i)})$ 
    \STATE $t \leftarrow t + 1$
    \STATE 更新有偏一阶矩估计： $\Vs \leftarrow \rho_1 \Vs + (1-\rho_1) \Vg$
    \STATE 更新有偏二阶矩估计：$\Vr \leftarrow \rho_2 \Vr + (1-\rho_2) \Vg \odot \Vg$
    \STATE 修正一阶矩的\gls{bias_sta}：$\hat{\Vs} \leftarrow \frac{\Vs}{1-\rho_1^t}$
    \STATE 修正二阶矩的\gls{bias_sta}：$\hat{\Vr} \leftarrow \frac{\Vr}{1-\rho_2^t}$
    \STATE 计算更新：$\Delta \Vtheta = - \epsilon \frac{\hat{\Vs}}{\sqrt{\hat{\Vr}} + \delta}$ \ \  （逐元素应用操作）
    \STATE 应用更新：$\Vtheta \leftarrow \Vtheta + \Delta \Vtheta$
\ENDWHILE
\end{algorithmic}
\end{algorithm}


% -- 301 --

\subsection{选择正确的优化算法}
\label{sec:choosing_the_right_optimization_algorithms}
在本节中，我们讨论了一系列算法，通过自适应每个模型参数的学习速率以解决优化\gls{deep_model}中的难题。
此时，一个自然的问题是：该选择哪种算法呢？

遗憾的是，目前在这一点上没有达成共识。
\cite{Schaul2014_unittests}展示了许多优化算法在大量学习任务上的价值比较。
虽然结果表明，具有自适应学习率（由RMSProp和AdaDelta代表）的算法族表现得相当鲁棒，但没有单一的算法表现为最好的。

目前，最流行的活跃使用的优化算法包括SGD，具动量的SGD，RMSProp，具动量的RMSProp，AdaDelta和Adam。
此时，选择哪一个算法似乎主要取决于使用者对算法的熟悉程度（以便调节超参数）。

\section{二阶近似方法}
\label{sec:approximate_second_order_methods}
在本节中，我们会讨论训练\gls{DNN}的二阶方法。
参看\cite{lecun1998mnist}了解该问题的早期处理方法。
为表述简单起见，我们只考察目标函数为经验风险：
\begin{equation}
    J(\Vtheta) = \SetE_{\RVx, \RSy \sim \hat{p}_{\text{data}}(\Vx,y) } [ L(f(\Vx; \Vtheta), y) ] =
\frac{1}{m} \sum_{i=1}^m L(f(\Vx^{(i)}; \Vtheta), y^{(i)}).
\end{equation}
然而，我们在这里讨论的方法很容易扩展到更一般的目标函数，例如，\chapref{chap:regularization_for_deep_learning}讨论的包括参数正则项的函数。

% -- 302 --

\subsection{牛顿方法}
\label{sec:newton_method}
在\secref{sec:gradient_based_optimization}，我们介绍了二阶梯度方法。
与一阶方法相比，二阶方法使用二阶导数改进了优化。
最广泛使用的二阶方法是牛顿法。
我们现在更详细地描述牛顿法，重点在其应用于神经网络的训练。

牛顿法是基于二阶泰勒级数展开在某点$\Vtheta_0$附近来近似$J(\Vtheta)$的优化方法，其忽略了高阶导数：
\begin{equation}
    J(\Vtheta) \approx J(\Vtheta_0) + (\Vtheta - \Vtheta_0)^\top \nabla_{\Vtheta}   
    J(\Vtheta_0) + \frac{1}{2} (\Vtheta - \Vtheta_0)^\top \MH(\Vtheta - \Vtheta_0),
\end{equation}
其中$\MH$是$J$相对于$\Vtheta$的\gls{hessian}矩阵在$\Vtheta_0$处的估计。
如果我们再求解这个函数的临界点，我们将得到牛顿参数更新规则：
\begin{equation}
\label{eq:8.27}
    \Vtheta^* = \Vtheta_0 - \MH^{-1}\nabla_{\Vtheta} J(\Vtheta_0).
\end{equation}
因此，对于局部的二次函数（具有正定的$\MH$），用$\MH^{-1}$重新调整梯度，牛顿法会直接跳到极小值。
如果目标函数是凸的但非二次的（有高阶项），该更新会是迭代的，得到和牛顿法相关的算法，如\algref{alg:newton}所示。

对于非二次的表面，只要\gls{hessian}保持正定，牛顿法能够迭代地使用。
这意味着一个两步迭代过程。
首先，更新或计算\gls{hessian}逆（通过更新二阶近似）。
其次，根据\eqnref{eq:8.27}更新参数。

% -- 303 --

在\secref{sec:plateaus_saddle_points_and_other_flat_regions}，我们讨论了牛顿法只适用于\gls{hessian}是正定的情况。
在深度学习中，目标函数的表面通常具有非凸的很多特点，如\gls{saddle_points}。
因此使用牛顿法是有问题的。
如果\gls{hessian}矩阵的特征值并不都是正的，例如，靠近\gls{saddle_points}处，牛顿法实际上会导致更新朝错误的方向移动。
这种情况可以通过正则化\gls{hessian}来避免。
常用的正则化技巧包括在\gls{hessian}矩阵对角线上增加常数$\alpha$。
正则化更新变为
\begin{equation}
    \Vtheta^* = \Vtheta_0 - [ H( f(\Vtheta_0)) + \alpha \MI  ]^{-1} \nabla_{\Vtheta} f(\Vtheta_0).
\end{equation}
这个正则化技巧用于牛顿法的近似，例如Levenberg-Marquardt算法\citep{Levenberg44,Marquardt63}，只要\gls{hessian}矩阵的负特征值仍然相对接近零，就会效果很好。
在曲率有更极端方向的情况下，$\alpha$的值必须足够大，以抵消负特征值。
然而，如果$\alpha$持续增加，\gls{hessian}矩阵会变得由对角矩阵$\alpha \MI$主导，通过牛顿法所选择的方向会收敛到普通梯度除以$\alpha$。
当很强的负曲率存在时，$\alpha$可能需要特别大，以至于牛顿法比选择合适学习率的梯度下降的步长更小。

\begin{algorithm}[ht]
\caption{目标为$J(\Vtheta)= \frac{1}{m} \sum_{i=1}^m L(f(\Vx^{(i)};\Vtheta), y^{(i)})$的牛顿法}
\label{alg:newton}
\begin{algorithmic}
\REQUIRE 初始参数$\Vtheta_{0}$
\REQUIRE 包含 $m$个样本的训练集
\WHILE{没有达到停止\gls{criterion}} 
      \STATE 计算梯度： $\Vg \leftarrow 
     \frac{1}{m} \nabla_{\Vtheta} \sum_i L(f(\Vx^{(i)};\Vtheta),\Vy^{(i)})$ 
      \STATE 计算\gls{hessian}：$\MH \leftarrow  
     \frac{1}{m} \nabla_{\Vtheta}^2 \sum_i L(f(\Vx^{(i)};\Vtheta),\Vy^{(i)})$ 
    \STATE 计算\gls{hessian}逆：$\MH^{-1}$
    \STATE 计算更新： $\Delta \Vtheta = - \MH^{-1} \Vg$
    \STATE 应用更新：$\Vtheta = \Vtheta+\Delta \Vtheta$
\ENDWHILE
\end{algorithmic}
\end{algorithm}


除了目标函数的某些特征带来的挑战，如\gls{saddle_points}，牛顿法用于训练大型神经网络还受限于其显著的计算负担。
\gls{hessian}矩阵中元素树木是参数数量的平方，因此，如果参数数目为$k$（甚至是在非常小的神经网络中$k$也可能是百万级别），牛顿法需要计算$k\times k$矩阵的逆，计算复杂度为$O(k^3)$。
另外，由于参数将每次更新都会改变，每次训练迭代都需要计算\gls{hessian}矩阵的逆。
其结果是，只有参数很少的网络才能在实际中用牛顿法训练。
在本节的剩余部分，我们将讨论一些试图保持牛顿法优点，同时避免计算障碍的替代算法。

\subsection{\glsentrytext{CG}}
\label{sec:conjugate_gradients}
\gls{CG}是一种通过迭代下降的\firstgls{conjugate_directions}以有效避免\gls{hessian}矩阵求逆计算的方法。
这种方法的灵感来自于最速下降方法弱点的仔细研究（详细信息请参看\secref{sec:gradient_based_optimization}），其中线性搜索迭代地用于梯度相关的方向中。
\figref{fig:chap8_steepest_descent_quadratic}说明了该方法在二次碗型目标中如何表现的，是一个相当无效的来回往复，锯齿形模式。
这是因为每一个由梯度给定的线性搜索方向，都保证正交于上一个线性搜索方向。

\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter8/figures/steepest_descent_quadratic_color}}
\fi
\caption{将最速下降法应用于二次代价表面。
在每个步骤，最速下降法沿着由初始点处的梯度定义的线跳到最低代价的点。
这解决了\figref{chap4_poor_conditioning_color}中使用固定学习速率所遇到的一些问题，但即使使用最佳步长，算法仍然朝最优方向曲折前进。
根据定义，在沿着给定方向的目标最小值处，最终点处的梯度与该方向正交。
}
\label{fig:chap8_steepest_descent_quadratic}
\end{figure}


% -- 304 --

假设上一个搜索方向是$\Vd_{t-1}$。   
在极小值处，线性搜索终止，方向$\Vd_{t-1}$处的方向导数为零：$\nabla_{\Vtheta} J(\Vtheta) \cdot \Vd_{t-1} = 0$。
因为该点的梯度定义了当前的搜索方向，$\Vd_t = \nabla_{\Vtheta} J(\Vtheta)$将不会贡献于方向$\Vd_{t-1}$。
因此方向$\Vd_t$正交于$\Vd_{t-1}$。
最速下降多次迭代中，方向$\Vd_{t-1}$和$\Vd_t$之间的关系如\figref{fig:chap8_steepest_descent_quadratic}所示。
如图展示的，下降正交方向的选择不会保持前一搜索方向上的最小值。
这产生了锯齿形的过程。
在当前梯度方向下降到极小值，我们必须重新最小化之前梯度方向上的目标。
因此，通过遵循每次线性搜索结束时的梯度，我们在某种意义上撤销了在之前线性搜索的方向上取得的进展。
\gls{CG}试图解决这个问题。

在\gls{CG}法，我们寻求一个和先前线性搜索方向\firstgls{conjugate}的搜索方向，即它不会撤销该方向上的进展。
在训练迭代$t$时，下一步的搜索方向$\Vd_t$的形式如下：
\begin{equation}
    \Vd_t = \nabla_{\Vtheta} J(\Vtheta) + \beta_t \Vd_{t-1},
\end{equation}
其中，系数$\beta_t$的大小控制我们应沿方向$\Vd_{t-1}$加回多少到当前搜索方向上。

% -- 305 --

两个方向$\Vd_t$和$\Vd_{t-1}$被称为共轭的，如果$\Vd_t^\top \MH \Vd_{t-1} = 0$，其中$\MH$是\gls{hessian}矩阵。

适应共轭的直接方法会涉及到$\MH$特征向量的计算以选择$\beta_t$。
这将无法满足我们发展对于大问题比牛顿法更加计算可行的方法的目标。
我们能不进行这些计算而得到共轭方向么？
幸运的是这个问题的答案是肯定的。

两种用于计算$\beta_t$的流行方法是：
\begin{enumerate}
\item Fletcher-Reeves:
\begin{equation}
    \beta_t = \frac{ \nabla_{\Vtheta} J(\Vtheta_t)^\top \nabla_{\Vtheta} J(\Vtheta_t) }
{ \nabla_{\Vtheta} J(\Vtheta_{t-1})^\top \nabla_{\Vtheta} J(\Vtheta_{t-1}) }
\end{equation}

\item Polak-Ribi\`{e}re:
\begin{equation}
    \beta_t = \frac{ (\nabla_{\Vtheta} J(\Vtheta_t) - \nabla_{\Vtheta} J(\Vtheta_{t-1}))^\top \nabla_{\Vtheta} J(\Vtheta_t) }
{ \nabla_{\Vtheta} J(\Vtheta_{t-1})^\top \nabla_{\Vtheta} J(\Vtheta_{t-1}) }
\end{equation}
\end{enumerate}
对于二次曲面而言，共轭方向确保梯度沿着前一方向大小不变。
因此，我们在前一方向上仍然是极小值。
其结果是，在$k$-维参数空间中，\gls{CG}只需要至多$k$次线性搜索就能达到极小值。
\gls{CG}算法如\algref{alg:cg}所示。

\begin{algorithm}[ht]
\caption{\gls{CG}方法}
\label{alg:cg}
\begin{algorithmic}
\REQUIRE 初始参数 $\Vtheta_{0}$
\REQUIRE 包含$m$个样本的训练集
\STATE 初始化 $\Vrho_{0} = 0$
\STATE 初始化 $g_0 = 0$
\STATE 初始化 $t = 1$
\WHILE{没有达到停止\gls{criterion}}
    \STATE 初始化梯度 $\Vg_{t} = 0$
    \STATE 计算梯度：$\Vg_{t} \leftarrow
         \frac{1}{m}\nabla_{\Vtheta} \sum_i L(f(\Vx^{(i)};\Vtheta),\Vy^{(i)})$ 
    \STATE 计算 $\beta_{t} = \frac{(\Vg_{t}-\Vg_{t-1})^\top \Vg_{t}}{\Vg_{t-1}^\top \Vg_{t-1}}$  (Polak-Ribi\`{e}re)
    \STATE (非线性\gls{CG}：视情况可重置$\beta_{t}$为零，
           例如  $t$是常数$k$的倍数时，如 $k=5$)
    \STATE 计算搜索方向： $\Vrho_{t} = -\Vg_{t} + \beta_{t} \Vrho_{t-1}$ 
    \STATE 执行\gls{line_search}寻找：$\epsilon^{*} = \arg\!\min_{\epsilon}
    \frac{1}{m} \sum_{i=1}^{m}L(f(\Vx^{(i)};\Vtheta_t + \epsilon \Vrho_t),\Vy^{(i)})$ 
    \STATE （对于真正二次的\gls{cost_function}，存在$\epsilon^*$的解析解，而无需显式地搜索）
    \STATE 应用更新：$\Vtheta_{t+1} = \Vtheta_{t}+ \epsilon^{*} \Vrho_{t}$
    \STATE $t \leftarrow t + 1$
\ENDWHILE
\end{algorithmic}
\end{algorithm}


\textbf{\gls{nonlinear_CG}：}
目前，我们已经讨论了\gls{CG}法用于二次目标函数。
当然，本章我们主要关注于探索训练神经网络和其他相关深度学习模型的优化方法，其对应的目标函数比二次函数复杂得多。
或许令人惊讶，\gls{CG}法在这种情况下仍然是适用的，尽管有一些修改。
没有目标是二次的保证，共轭方向也不再保证在以前方向上目标仍是极小值。
其结果是，\textbf{\gls{nonlinear_CG}}算法会包括一些偶尔的重设，\gls{CG}法沿未修改的梯度重启线性搜索。

% -- 306 --

实践者报告在实践中使用\gls{nonlinear_CG}算法训练神经网络是合理的，尽管在开始\gls{nonlinear_CG}前使用随机梯度下降迭代若干步来初始化效果更好。
另外，尽管（非线性）\gls{CG}算法传统上作为批方法，\gls{minibatch}版本已经成功用于训练神经网络\citep{LeRoux-chapter-2011}。
针对神经网路的\gls{CG}应用早已被提出，例如放缩的\gls{CG}算法\citep{Moller}。

\subsection{\glsentrytext{BFGS}}
\label{sec:bfgs}
\textbf{Broyden-Fletcher-Goldfarb-Shanno}（\textbf{\gls{BFGS}}）算法具有牛顿法的一些优点，但没有牛顿法的计算负担。
在这方面，\gls{BFGS}和CG很像。
然而，\gls{BFGS}使用了一个更直接的方法近似牛顿更新。回顾牛顿更新由下式给出
\begin{equation}
    \Vtheta^* = \Vtheta_0 - \MH^{-1} \nabla_{\Vtheta} J(\Vtheta_0),
\end{equation}
其中，$\MH$是$J$相对于$\Vtheta$的\gls{hessian}矩阵在$\Vtheta_0$处的估计。
运动牛顿法的主要计算难点在于计算\gls{hessian}逆$\MH^{-1}$。
拟牛顿法所采用的方法（\gls{BFGS}是其中最突出的）是用矩阵$\MM_t$近似逆，迭代地低秩更新精度以更好近似$\MH^{-1}$。

% -- 307 --

\gls{BFGS}近似的说明和推导出现在很多关于优化的教科书中，包括\cite{Lue84}。

当\gls{hessian}逆近似$\MM_t$更新时，下降方向$\Vrho_t$为$\Vrho_t = \MM_t \Vg_t$。
该方向上的线性搜索用于决定该方向上的步长$\epsilon^*$。
参数的最后更新为：
\begin{equation}
    \Vtheta_{t+1} = \Vtheta_t + \epsilon^* \Vrho_t.
\end{equation}

和\gls{CG}法相似，\gls{BFGS}算法迭代一系列线性搜索，其方向含二阶信息。
然而和\gls{CG}不同的是，该方法的成功并不严重依赖于线性搜索寻找该方向上和真正极小值很近的一点。
因此，相比于\gls{CG}，\gls{BFGS}的优点是其花费更少的时间改进每个线性搜索。
在另一方面，\gls{BFGS}算法必须存储\gls{hessian}逆矩阵$\MM$，需要$O(n^2)$的存储空间，使\gls{BFGS}不适用于大多数具有百万级参数的现代深度学习模型。

\textbf{存储限制的\gls{BFGS}（或\gls{LBFGS}）}
通过避免存储完整的\gls{hessian}逆近似$\MM$，\gls{BFGS}算法的存储代价可以显著降低。
\gls{LBFGS}算法使用和\gls{BFGS}算法相同的方法计算$\MM$的近似，但起始假设是$\MM^{(t-1)}$是单位矩阵，而不是一步一步都要存储近似。
如果使用精确的线性搜索，\gls{LBFGS}定义的方向会是相互共轭的。
然而，不同于\gls{CG}法，即使只是近似线性搜索的极小值，该过程的效果仍然不错。
这里描述的无存储的\gls{LBFGS}方法可以拓展为包含\gls{hessian}矩阵更多的信息，每步存储一些用于更新$\MM$的向量，且每步的存储代价是$O(n)$。

% -- 308 --

\section{优化技巧和元算法}
\label{sec:optimization_strategies_and_meta_algorithms}
许多优化技术并非真正的算法，而是一般化的模板，可以特定产生算法，或是并入到很多不同的算法中。

\subsection{\glsentrytext{batch_normalization}}
\label{sec:batch_normalization}
\gls{batch_normalization}\citep{Ioffe+Szegedy-2015}是优化\gls{DNN}中最激动人心的最新创新之一。
实际上它并不是一个优化算法，而是一个自适应的重新参数化的方法，试图解决训练非常深层模型的困难。

非常深层的模型会涉及多个函数或层组合。
在其他层不改变的假设下，梯度用于如何更新每一个参数。
在实践中，我们同时更新所有层。
当我们进行更新时，可能会发生一些意想不到的结果，这是因为许多组合在一起的函数同时改变时，计算更新的假设是其他函数保持不变。
举一个简单的例子，假设我们有一个\gls{DNN}，每一层只有一个单元，并且在每个\gls{hidden_layer}不使用激励函数：$\hat{y} = xw_1 w_2 w_3 \dots w_l$。
这里，$w_i$表示用于层$i$的权重。层$i$的输出是$h_i = h_{i-1} w_i$。
输出$\hat{y}$是输入$x$的线性函数，但是权重$w_i$的非线性函数。
假设我们的损失函数$\hat{y}$上的梯度为$1$，所以我们希望稍稍降低$\hat{y}$。
然后反向传播算法可以计算梯度$\Vg = \nabla_{\Vw} \hat{y}$。
想想我们在更新$\Vw \leftarrow \Vw - \epsilon \Vg$时会发生什么。
近似$\hat{y}$的一阶泰勒级数会预测$\hat{y}$的值下降$\epsilon \Vg^\top \Vg$。
如果我们希望$\hat{y}$下降$0.1$，那么梯度中的一阶信息表明我们应设置学习率$\epsilon$为$\frac{0.1}{\Vg^\top \Vg}$。
然而，实际的更新将包括二阶，三阶，直到$l$阶的影响。
$\hat{y}$的更新值为
\begin{equation}
    x(w_1-\epsilon g_1)(w_2-\epsilon g_2)\dots(w_l-\epsilon g_l),
\end{equation}
这个更新中所产生的一个二阶项示例是$\epsilon^2 g_1 g_2 \prod_{i=3}^l w_i$ 。
如果 $\prod_{i=3}^l w_i$很小，那么该项可以忽略不计。而如果层$3$到层$l$的权重都比$1$大时，该项可能会指数级大。
这使得很难选择一个合适的学习速率，因为某一层中参数更新的效果很大程度上取决于其他所有层。
二阶优化算法通过考虑二阶相互影响来解决这个问题，但我们可以看到，在非常深的网络中，更高阶的相互影响会很显著。
即使是二阶优化算法，计算代价也很高，并且通常需要大量近似，以免真正计算所有的重要二阶相互作用。
因此对于$n>2$的情况建立$n$阶优化算法似乎是无望的。
那么我们可以做些什么呢？

% -- 309 --

\gls{batch_normalization}提出了一种几乎可以重新参数化所有\gls{deep_network}的优雅方法。
重新参数化显著减少了多层之间协调更新的问题。
\gls{batch_normalization}可应用于网络的任何输入层或\gls{hidden_layer}。
设$\MH$是需要标准化的某层的\gls{minibatch}激励函数，布置为设计矩阵，每个样本的激励出现在矩阵的每一行中。
标准化$\MH$，我们替代它为
\begin{equation}
\MH' = \frac{\MH - \Vmu}{\Vsigma},
\end{equation}
其中$\Vmu$是包含每个单元均值的向量，$\Vsigma$是包含每个单元标准差的向量。
此处的算术是基于广播向量$\Vmu$和向量$\Vsigma$应用于矩阵$\MH$的每一行。
在每一行内，运算是逐元素的，因此$H_{i,j}$标准化为减去$\mu_j$再除以$\sigma_j$。
网络的其余部分操作$\MH'$的方式和原网络操作$\MH$的方式一样。

在训练阶段，
\begin{equation}
    \Vmu = \frac{1}{m} \sum_i \MH_{i,:}
\end{equation}
和
\begin{equation}
    \Vsigma = \sqrt{ \delta + \frac{1}{m} \sum_i (\MH - \Vmu)_i^2 },
\end{equation}
其中$\delta$是个很小的正值，比如$10^{-8}$，以强制避免遇到$\sqrt{z}$的梯度在$z=0$处未定义的问题。
至关重要的是，\emph{我们反向传播这些操作}，计算均值和标准差，并应用它们于标准化$\MH$。
这意味着，梯度不会再简单地增加$h_i$的\gls{standard_deviation}或均值；标准化操作会除掉这一操作的影响，归零其在梯度中的元素。
这是\gls{batch_normalization}方法的一个重大创新。
以前的方法添加损失函数的惩罚，以鼓励单位标准化激励统计量，或是在每个梯度下降步骤之后重新标准化单位统计量。
前者通常会导致不完全的标准化，而后者通常会显著地消耗时间，因为学习算法会反复改变均值和方差而标准化步骤会反复抵消这种变化。
\gls{batch_normalization}重新参数化模型，以使一些单元总是被定义标准化，巧妙地回避了这两个问题。

% -- 310 --

在测试阶段，$\Vmu$和$\Vsigma$可以被替换为训练阶段收集的运行均值。
这使得模型可以对单一样本评估，而无需使用定义于整个\gls{minibatch}的$\Vmu$和$\Vsigma$。

回顾例子$\hat{y} = x w_1 w_2 \dots w_l$，我们看到，我们可以通过标准化$h_{l-1}$很大程度地解决学习这个模型的问题。
假设$x$采样自一个单位高斯。
那么$h_{l-1}$也是来自高斯，因为从$x$到$h_l$的变换是线性的。
然而，$h_{l-1}$不再有零均值和单位方差。
使用\gls{batch_normalization}后，我们得到的归一化$\hat{h}_{l-1}$恢复了零均值和单位方差的特性。
对于底层的几乎任意更新而言，$\hat{h}_{l-1}$仍然保持着单位高斯。
然后输出$\hat{y}$可以学习为一个简单的线性函数$\hat{y} = w_l \hat{h}_{l-1}$。
现在学习这个模型非常简单，因为低层的参数在大多数情况下没有什么影响；它们的输出总是重新标准化为单位高斯。
只在少数个例中，低层会有影响。
改变某个低层权重为$0$，可能退化输出；改变低层权重的符号可能反转$\hat{h}_{l-1}$和$y$之间的关系。
这些情况都是非常罕见的。
没有标准化，几乎每一个更新都会对$h_{l-1}$的统计量有着极端的影响。
因此，\gls{batch_normalization}显著地使得模型更易学习。
在这个示例中，容易学习的代价是使得底层网络没有用。
在我们的线性示例中，较低层不再有任何有害的影响，但它们也不再有任何有益的影响。
这是因为我们已经标准化了一阶和二阶统计量，这是线性网络可以影响的所有因素。
在具有非线性激励函数的\gls{DNN}中，较低层可以进行数据的非线性变换，所以它们仍然是有用的。
\gls{batch_normalization}仅标准化每个单元的均值和方差，以稳定化学习，但允许单元和单个单元的非线性统计量之间的关系发生变化。

由于网络的最后一层能够学习线性变换，实际上我们可能希望移除一层内单元之间的所有线性关系。
事实上，这是\cite{Desjardins2015}中采用的方法，为\gls{batch_normalization}提供了灵感。
令人遗憾的是，消除所有的线性关联比标准化各个独立单元的均值和\gls{standard_deviation}代价更高，因此迄今\gls{batch_normalization}仍是最实用的方法。

% -- 311 --

标准化一个单元的均值和标准差会降低包含该单元的神经网络的表达能力。
为了保持网络的表现力，通常会取代\gls{batch}\gls{hidden_unit}激励$\MH$为$\gamma \MH' + \Vbeta$，而不是简单地使用标准化的$\MH'$。
变量$\Vgamma$和$\Vbeta$是允许新变量有任意均值和\gls{standard_deviation}的学习参数。
乍一看，这似乎是无用的——为什么我们将均值设为$0$，然后又引入参数允许它被重设为任意值$\Vbeta$？
答案是，新的参数可以表示旧参数作为输入的同一族函数，但是新参数有不同的学习动态。
在旧参数中，$\MH$的均值取决于$\MH$下层中参数的复杂关联。
在新参数中，$\Vgamma \MH' + \Vbeta$的均值仅由$\Vbeta$确定。
新参数很容易通过梯度下降来学习。

大多数神经网络层会采取形式$\phi(\MX\MW+ \Vb)$，其中$\phi$是某个固定的非线性激励函数，如\gls{rectified_linear}变换。
自然想到是否我们应该应用\gls{batch_normalization}于输入$\MX$，或是变换值$\MX\MW+\Vb$。
\cite{Ioffe+Szegedy-2015}推荐后者。
更具体地，$\MX\MW+\Vb$应替换为$\MX\MW$的标准化形式。
偏置项应被忽略，因为参数$\Vbeta$会加入\gls{batch_normalization}重新参数化，它是冗余的。
一层的输入通常是前一层的非线性激励函数，如\gls{rectified_linear}函数，的输出。
因此，输入的统计量更符合非高斯，而更不服从线性操作的标准化。

\chapref{chap:convolutional_networks}所述的卷积网络，在特征映射中每个空间位置同样地标准化$\Vmu$和$\Vsigma$是很重要的，能使特征映射的统计量不因空间位置而保持相同。

\subsection{坐标下降}
\label{sec:coordinate_descent}
在某些情况下，将一个优化问题分解成几个部分，可以更快地解决原问题。
如果我们最小化$f(\Vx)$相对于某个单一变量$x_i$，然后相对于另一个变量$x_j$，等等，反复循环所有的变量，我们会保证到达（局部）极小值。
这种做法被称为\firstgls{coordinate_descent}，因为我们一次优化一个坐标。
更一般地，\firstgls{block_coordinate_descent}是指对于某个子集的变量同时最小化。
术语``\gls{coordinate_descent}''通常既指块坐标下降，也指严格的单个坐标下降。

% -- 312 --

当优化问题中的不同变量能够清楚地分成相对独立的组，或是当优化一组变量明显比优化所有变量效率更高时，坐标下降最有意义。
例如，考虑损失函数
\begin{equation}
    J(\MH, \MW) = \sum_{i,j} |H_{i,j}| + \sum_{i,j} \left( \MX - \MW^\top \MH \right)_{i,j}^2 .
\end{equation}
该函数描述了一种被称为\gls{sparse_coding}的学习问题，其目标是寻求一个权重矩阵$\MW$，可以线性解码激励值矩阵$\MH$以重构训练集$\MX$。
\gls{sparse_coding}的大多数应用还涉及到权重衰减或$\MW$列范数的约束，以免极小$\MH$和极大$\MW$的病态解。

函数$J$不是凸的。
然而，我们可以将训练算法的输入分成两个集合：字典参数$\MW$和编码表示$\MH$。
最小化关于这两者之一的任意一组变量的目标函数都是凸问题。
因此，块坐标下降允许我们使用高效的凸优化算法，交替固定$\MH$优化$\MW$和固定$\MW$优化$\MH$。

当一个变量的值很大程度地影响另一个变量的最优值时，坐标下降不是一个很好的方法，如函数$f(\Vx)=(x_1 - x_2)^2+\alpha(x_1^2 + x_2^2)$，其中$\alpha$是正值常数。
第一项鼓励两个变量具有相似的值，而第二项鼓励它们接近零。
解是两者都为零。
牛顿法可以一步解决这个问题，因为它是一个正定二次问题。
但是，对于小值$\alpha$而言，坐标下降会使进展非常缓慢，因为第一项不允许单个变量变为和其他变量当前值显著不同的值。


\subsection{Polyak平均}
\label{sec:polyak_averaging}
Polyak平均\citep{Polyak+Juditsky-1992}会平均优化算法在参数空间访问轨迹中的几个点。
如果$t$次迭代梯度下降访问了点$\Vtheta^{(1)},\dots,\Vtheta^{(t)}$，那么Polyak平均算法的输出是$\hat{\Vtheta}^{(t)} = \frac{1}{t} \sum_i \Vtheta^{(i)}$。
在某些问题中，如梯度下降应用于凸问题，这种方法具有较强的收敛保证。
当应用于神经网络时，其验证更多是启发式的，但在实践中表现良好。
基本想法是，优化算法可能会来回穿过山谷好几次而没经过山谷底部附近的点。
尽管两边所有位置的均值应比较接近谷底。

% -- 313 --

在非凸问题中，优化轨迹的路径可以非常复杂，经过了许多不同的区域。
包括参数空间中遥远过去的点，可能与当前点在损失函数上相隔很大的障碍，看上去不像一个有用的行为。
其结果是，当应用Polyak平均于非凸问题时，通常会使用指数衰减计算平均值：
\begin{equation}
    \hat{\Vtheta}^{(t)} = \alpha \hat{\Vtheta}^{(t-1)} + (1-\alpha) \Vtheta^{(t)} .
\end{equation}

这个计算平均值的方法被用于大量数值应用中。最近的例子请参看\cite{Szegedy-et-al-2015}。

\subsection{监督\glsentrytext{pretraining}}
\label{sec:supervised_pretraining}
有时，如果模型太复杂难以优化，或是如果任务非常困难，直接训练模型来解决特定任务可能太过挑战。
有时训练一个较简单的模型来求解问题，然后使模型更复杂会更有效。
训练模型来求解一个简化的问题，然后转移到最后的问题，有时也会更有效些。
这些在直接训练目标模型求解目标问题之前，训练简单模型求解简化问题的方法统称为\firstgls{pretraining}。


\firstgls{greedy_algorithm}将问题分解成许多部分，然后独立地在每个部分求解最优值。
令人遗憾的是，结合各个最佳的部分不能保证得到一个最佳的完整解。
然而，贪心算法计算上比求解最优联合解的算法高效得多，并且贪心算法的解在不是最优的情况下，往往也是可以接受的。
贪心算法也可以后跟一个\firstgls{fine_tuning}阶段，联合优化算法搜索全问题的最优解。
使用贪心解初始化联合优化算法，可以极大地加速算法，并提高寻找到的解的质量。

\gls{pretraining}算法，特别是贪心\gls{pretraining}，在深度学习中是普遍存在的。
在本节中，我们会具体描述这些将监督学习问题分解成其他简化的监督学习问题的\gls{pretraining}算法。
这种方法被称为\firstgls{greedy_supervised_pretraining}。

% -- 314 --

在\gls{greedy_supervised_pretraining}的原始版本\citep{Bengio-nips-2006-short}中，每个阶段包括一个仅涉及最终神经网络的子集层的监督学习训练任务。
\gls{greedy_supervised_pretraining}的一个例子如\figref{fig:chap8_deep_sup}所示，其中每个附加的\gls{hidden_layer}作为浅监督MLP的一部分\gls{pretraining}，以先前训练的\gls{hidden_layer}输出作为输入。
并非一次\gls{pretraining}一层，\cite{Simonyan2015}\gls{pretraining}深度卷积网络（11层权重），然后使用该网络前四层和最后三层初始化更深的网络（多达19层权重）。
非常深的新网络的中间层是随机初始化的。
然后联合训练新网络。
还有一种选择，由\cite{Yu+al-2010}提出，将先前训练MLP的\emph{输出}，以及原始输入，作为每个附加阶段的输入。

\begin{figure}[!htb]
\ifOpenSource
\centerline{\includegraphics{figure.pdf}}
\else
\centerline{\includegraphics{Chapter8/figures/deep_sup}}
\fi
\caption{一种形式的\gls{greedy_supervised_pretraining}的示意图~\citep{Bengio-nips-2006-small}。
(a)我们从训练一个足够浅的架构开始。
(b)同一个架构的另一描绘。
(c)我们只保留原始网络的输入到隐藏层，并丢弃隐藏到输出层。 
我们将第一层\gls{hidden_layer}的输出作为输入发送到另一监督单隐层\glssymbol{MLP}（使用与第一个网络相同的目标训练），从而可以添加第二层\gls{hidden_layer}。 
这可以根据需要重复多层。
(d)所得架构的另一种描绘，可视为前馈网络。 
为了进一步改进优化，我们可以联合地\gls{fine_tuning}所有层（仅在该过程的结束或者该过程的每个阶段）。
}
\label{fig:chap8_deep_sup}
\end{figure}


为什么\gls{greedy_supervised_pretraining}会有帮助呢？
最初由\cite{Bengio-nips-2006}提出的假说是，其有助于更好地指导深层结构的中间层的学习。
一般情况下，\gls{pretraining}在优化和泛化两边面都是有帮助的。

另一个与监督\gls{pretraining}有关的方法扩展了迁移学习的想法：\cite{yosinski-nips2014}在一组任务上\gls{pretraining}了$8$层权重的深度卷积网络（1000个ImageNet对象类的子集），然而用该网络的前$k$层初始化同样规模的网络。
然后第二个网络的所有层（上层随机初始化）联合训练以执行不同的任务（1000个ImageNet对象类的另一个子集），但训练样本少于第一个任务。
神经网络中另一个和迁移学习相关的方法将在\secref{sec:transfer_learning_and_domain_adaptation}讨论。

另一条相关的工作线是\textbf{FitNets}\citep{Romero-et-al-ICLR2015-small}方法。
这种方法始于训练深度足够低和宽度足够大（每层单元数），容易训练的网络。
然后，这个网络成为第二个网络（被指定为\textbf{学生}）的\textbf{老师}。
学生网络更深更窄（11至19层），且在正常情况下很难用SGD训练。
训练学生网络不仅需要预测原任务的输出，还需要预测教师网络中间层的值，这样使得训练学生网络变得更容易。
这个额外的任务说明了\gls{hidden_layer}应如何使用，能够简化优化问题。
附加参数被引入来从更深的学生网络中间层去回归$5$层教师网络的中间层。
然而，并非预测最终分类目标，该目标是预测教师网络的中间\gls{hidden_layer}。
学生网络的低层因而具有两个目标：学生网络的输出完成其目标，和预测教师网络的中间层。
尽管一个窄而深的网络似乎比宽而浅的网络更难训练，但窄而深网络的泛化能力可能更好，
并且如果其足够窄，参数足够少，那么其计算代价更小。
没有\gls{hidden_layer}的提示，学生网络在训练集和测试集上的实验表现都很差。
因而中间层的提示是有助于训练很难训练的网络的方法之一，但是其他优化技术或是架构上的变化也可能解决这个问题。

% -- 316 --

\subsection{设计有助于优化的模型}
\label{sec:designing_models_to_aid_optimization}
改进优化的最好方法并不总是改进优化算法。
相反，\gls{deep_model}中优化的许多改进来自于设计易于优化的模型。

原则上，我们可以使用呈锯齿非单调模式上上下下的激励函数，但是，这将使优化极为困难。
在实践中，\emph{选择一族容易优化的模型比使用一个强大的优化算法更重要}。
神经网络学习在过去30年的大多数进步主要来自于改变模型族，而非改变优化过程。
1980年代用于训练神经网络的带动量的随机梯度下降，仍然是现代神经网络应用中的前沿算法。

具体来说，现代神经网络的\emph{设计选择}体现在层之间的线性变换，几乎处处可导的激励函数，和大部分定义域都有明显的梯度。
特别地，创新的模型，如\glssymbol{LSTM}，\gls{ReLU}和\gls{maxout}单元都比先前的模型（如基于\gls{sigmoid}单元的\gls{deep_network}）使用更多的线性函数。
这些模型都具有简化优化的性质。
如果线性变换的雅可比具有相对合理的奇异值，那么梯度能够流经很多层。
此外，线性函数在一个方向上一致增加，所以即使模型的输出远离正确值，也可以简单清晰地计算梯度，使其输出方向朝降低损失函数的方向移动。
换言之，现代神经网络的设计方案旨在使其\emph{局部}梯度信息合理地对应着移向一个遥远的解。

其他的模型设计技巧有助于使优化更简单。
例如，层之间的线性路径或是跳过连接减少了从较低层参数到输出最短路径的长度，因而缓解了梯度消失的问题\citep{Srivastava-et-al-arxiv2015}。
一个和跳过连接相关的想法是添加和网络中间\gls{hidden_layer}相连的输出的额外副本，如GoogLeNet\citep{Szegedy-et-al-arxiv2014}和深度监督网络\citep{Lee-et-al-2014}。
这些``辅助头''被训练来执行和网络顶层主要输出相同的任务，以确保底层网络能够接受较大的梯度。
当训练完成时，辅助头可能被丢弃。
这是之前小节介绍到的\gls{pretraining}技巧的替代方法。
以这种方式，我们可以在一个阶段联合训练所有层，而不改变架构，使得中间层（特别是低层）能够通过更短的路径得到一些有些如何更新的有用信息。
这些信息为底层提供了误差信号。

% -- 317 --

\subsection{连续方法和课程学习}
\label{sec:continuation_methods_and_curriculum_learning}
正如\secref{sec:poor_correspondence_between_local_and_global_structure}探讨的，许多优化挑战都来自于损失函数的全局结构，不能仅通过局部更新方向上更好的估计来解决。
解决这个问题的主要方法是尝试初始化参数在一个区域内，该区域可以在参数空间中通过一个局部下降能发现的短路径连接到解。

\firstgls{continuation_method}是一族通过挑选初始点使优化更容易的方法，以确保局部优化花费大部分时间在表现良好的空间。
\gls{continuation_method}的背后想法是构造一系列具有相同参数的目标函数。
为了最小化代价函数$J(\Vtheta)$，我们构建新的损失函数$\{J^{(0)},\dots,J^{(n)}\}$这些损失函数逐步提高难度，其中$J^{(0)}$是最容易最小化的，$J^{(n)}$是最难的，真正的损失函数促进整个过程。
当我们说$J^{(i)}$比$J^{(i+1)}$更容易时，是指其在更多的$\Vtheta$空间上表现良好。
随机初始化更有可能落入局部下降可以成功最小化损失函数的区域，因为其良好区域更大。
这系列损失函数设计为前一个解是下一个的良好初始点。
因此，我们首先解决一个简单的问题，然后改进解以解决逐步变难的问题，直到我们求解真正问题的解。

传统的\gls{continuation_method}（用于神经网络训练之前的连续方法）通常是基于平滑的目标函数。
参看\cite{Wu-97}了解这类方法的示例，以及一些相关方法的综述。
\gls{continuation_method}也和参数中加入\gls{noise}的模拟退火紧密相关\citep{Kirkpatrick83}。
\gls{continuation_method}在最近几年非常成功。
参看\cite{Mobahi+Fisher-AAAI2015}了解其近期文献的概述，特别是在\glssymbol{AI}方面的应用。

% -- 318 --

传统上，\gls{continuation_method}主要用来克服局部极小值的问题。
具体地，它被设计来在有很多局部极小值的情况下，求解一个全局极小值。
这些连续方法会通过``模糊''原来的损失函数来构建更容易的损失函数。
这些模糊操作可以是用采样来近似
\begin{equation}
    J^{(i)}(\Vtheta) = \SetE_{\theta' \sim \mathcal{N}(\Vtheta'; \Vtheta, \sigma^{(i)2})} J(\Vtheta')
\end{equation}
这个方法的直觉是有些非凸函数在模糊后会近似凸的。
在许多情况下，这种模糊保留了关于全局极小值的足够信息，我们可以通过逐步求解更少模糊的问题来求解全局极小值。
这种方法有三种可能失败的方式。
首先，它可能成功地定义了一连串损失函数，并从开始的一个凸函数起（逐一地）沿着函数链最佳轨迹逼近全局最小值，但可能需要非常多的逐步损失函数，整个过程的成本仍然很高。
另外，即使\gls{continuation_method}可以适用，NP难的优化问题仍然是NP难的。
其他两种\gls{continuation_method}失败的原因是不实用。
其一，不管如何模糊，可能函数没法变成凸的，比如函数$J(\Vtheta) = -\Vtheta^\top \Vtheta$。
其二，函数可能在模糊后是凸的，但模糊函数的最小值可能会逐步到一个局部值，而非原始损失函数的全局最小值。
尽管\gls{continuation_method}最初用来解决局部最小值的问题，局部最小值已不再是神经网络优化中的主要问题了。
幸运的是，\gls{continuation_method}仍然有所帮助。
\gls{continuation_method}引入的简化目标函数能够消除平坦区域，减少梯度估计的方差，提高\gls{hessian}矩阵的条件数，使局部更新更容易计算，或是改进局部更新方向和朝向全局解方向之间的对应关系。

\cite{Bengio+al-2009}指出被称为\firstgls{curriculum_learning}或者\firstgls{shaping}的方法可以解释为\gls{continuation_method}。
\gls{curriculum_learning}规划学习过程的想法是，首先学习简单的概念，然后逐步学习依赖于这些简化概念的复杂概念。
之前这一基本技巧被用来加速动物训练过程\citep{Skinner1958,Peterson2004,Krueger+Dayan-2009}和机器学习过程\citep{solomonoff1989system,Elman93,Sanger-1994}。
\cite{Bengio+al-2009}验证这一技巧为\gls{continuation_method}，通过增加简单样本的影响（通过分配它们较大的系数到损失函数，或者更频繁地采样），先前的$J^{(i)}$会容易。
实验证明，在大规模的神经语言模型任务上使用\gls{curriculum_learning}，可以获得更好的结果。
课程学习已经成功应用于大量的自然语言\citep{Spitkovsky-et-al-HLT2010,collobert2011natural,Mikolov-ASRU-2011,Tu+Honavar-IJCAI2011}和计算机视觉\citep{Kumar+al-2010,Lee+Grauman-CVPR2011,Supancic+Ramanan-CVPR2013}任务上。
\gls{curriculum_learning}被证实为与人类教学方式一致\citep{Khan+Zhu+Mutlu-2011}：
教师刚开始会展示更容易，更典型的示例，然后帮助学习者在不太显然的情况下提炼决策面。
在人类教学上，基于\gls{curriculum_learning}的技巧比基于样本均匀采样的技巧更有效，也能提高其他学习技巧的效率\citep{Basu+Christensen-AAAI2013}。

% -- 319 --

\gls{curriculum_learning}研究的另一个重要贡献体现在训练循环神经网络抓住长期依赖：
\cite{Zaremba+Sutskever-arxiv2014}发现使用\emph{\gls{stochastic_curriculum}}获得了更好的结果，容易和困难的示例混合在一起，随机提供给学习者，更难示例（这些具有长期依赖）的平均比例在逐渐上升。
具有确定性课程，不再发现超过基线（完整训练集的普通训练）的改进。

现在我们已经介绍了一些基本的神经网络模型，以及如何正则和优化。
在接下来的章节中，我们转向神经网络的细化，扩展到能够处理很大规模的数据和具有特殊结构的数据。
在本章中讨论的优化算法在较少或者没有改动后，通常可以直接用于这些特殊的架构。

% -- 320 --



















